home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume25 / mtools2 / part01 next >
Encoding:
Text File  |  1992-01-10  |  66.7 KB  |  2,573 lines

  1. Newsgroups: comp.sources.unix
  2. From: fthood!egray@uxc.cso.uiuc.edu (Emmet P. Gray)
  3. Subject: v25i097: mtools2 - tools to manipulate MSDOS filesystems, V2.0, Part01/03
  4. Sender: sources-moderator@pa.dec.com
  5. Approved: vixie@pa.dec.com
  6.  
  7. Submitted-By: fthood!egray@uxc.cso.uiuc.edu (Emmet P. Gray)
  8. Posting-Number: Volume 25, Issue 97
  9. Archive-Name: mtools2/part01
  10.  
  11.                                 MTOOLS
  12.                               version 2.0
  13.  
  14. Mtools is a public domain collection of programs to allow Unix systems
  15. to read, write, and manipulate files on an MSDOS filesystem (typically a
  16. diskette).
  17.  
  18. The following MSDOS commands are emulated:
  19.  
  20.     ATTRIB, CD, COPY, DEL/ERASE, DIR, FORMAT, LABEL, MD/MKDIR,
  21.     RD/RMDIR, COPY, REN/RENAME, TYPE, and COPY.
  22.  
  23. #! /bin/sh
  24. # This is a shell archive.  Remove anything before this line, then unpack
  25. # it by saving it into a file and typing "sh file".  To overwrite existing
  26. # files, type "sh file -c".  You can also feed this as standard input via
  27. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  28. # will see the following message at the end:
  29. #        "End of archive 1 (of 3)."
  30. # Contents:  mtools mtools/Mattrib.1 mtools/Mcd.1 mtools/Mcopy.1
  31. #   mtools/Mdel.1 mtools/Mdir.1 mtools/Mformat.1 mtools/Mkmanifest.1
  32. #   mtools/Mlabel.1 mtools/Mmd.1 mtools/Mrd.1 mtools/Mread.1
  33. #   mtools/Mren.1 mtools/Mtools.1 mtools/Mtype.1 mtools/Mwrite.1
  34. #   mtools/Readme mtools/Release.notes mtools/buf_read.c
  35. #   mtools/devices.c mtools/dir_make.c mtools/expand.c
  36. #   mtools/fat_free.c mtools/fat_read.c mtools/fat_write.c
  37. #   mtools/file_read.c mtools/file_write.c mtools/is_dir.c
  38. #   mtools/match.c mtools/mkmanifest.c mtools/msdos.h mtools/parse.c
  39. #   mtools/patchlevel.h mtools/subdir.c
  40. # Wrapped by lai@risotto on Sat Jan 11 12:03:34 1992
  41. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  42. if test ! -d 'mtools' ; then
  43.     echo shar: Creating directory \"'mtools'\"
  44.     mkdir 'mtools'
  45. fi
  46. if test -f 'mtools/Mattrib.1' -a "${1}" != "-c" ; then 
  47.   echo shar: Will not clobber existing file \"'mtools/Mattrib.1'\"
  48. else
  49. echo shar: Extracting \"'mtools/Mattrib.1'\" \(1208 characters\)
  50. sed "s/^X//" >'mtools/Mattrib.1' <<'END_OF_FILE'
  51. X.TH MATTRIB 1 local
  52. X.SH NAME
  53. Xmattrib \- change MSDOS file attribute flags
  54. X.SH SYNOPSIS
  55. X.B mattrib
  56. X[
  57. X.B -a|+a
  58. X]
  59. X[
  60. X.B -h|+h
  61. X]
  62. X[
  63. X.B -r|+r
  64. X]
  65. X[
  66. X.B -s|+s
  67. X] msdosfile [ msdosfiles... ]
  68. X.SH DESCRIPTION
  69. X.I Mattrib
  70. Xwill add attribute flags to an MSDOS file (with the '+' operator) or
  71. Xremove attribute flags (with the '-' operator).
  72. X.PP
  73. X.I Mattrib
  74. Xwill allow the following command line options:
  75. X.TP
  76. X.B a
  77. XArchive bit.  Used by some backup programs to indicate a new file.
  78. X.TP
  79. X.B r
  80. XRead-only bit.  Used to indicate a read-only file.  Files with this bit
  81. Xset cannot be erased by DEL.  However, 
  82. X.I
  83. Xmdel
  84. Xis more cunning.
  85. X.TP
  86. X.B s
  87. XSystem bit.  Used by MSDOS to indicate a operating system file.
  88. X.TP
  89. X.B h
  90. XHidden bit.  Used to make files hidden from DIR.  However,
  91. X.I
  92. Xmdir
  93. Xis more cunning.
  94. X.PP
  95. XMSDOS subdirectory names are supported with either the '/' or '\e\'
  96. Xseparator.  The use of the '\e\' separator or wildcards will require the
  97. Xnames to be enclosed in quotes to protect them from the shell.
  98. X.PP
  99. XThe
  100. X.I mcd
  101. Xcommand may be used to establish the device and the current working
  102. Xdirectory (relative to MSDOS), otherwise the default is A:/.
  103. X.SH SEE ALSO
  104. Xmcd(1)
  105. X.SH BUGS
  106. XMost versions of ATTRIB don't allow this many options.
  107. END_OF_FILE
  108. if test 1208 -ne `wc -c <'mtools/Mattrib.1'`; then
  109.     echo shar: \"'mtools/Mattrib.1'\" unpacked with wrong size!
  110. fi
  111. # end of 'mtools/Mattrib.1'
  112. fi
  113. if test -f 'mtools/Mcd.1' -a "${1}" != "-c" ; then 
  114.   echo shar: Will not clobber existing file \"'mtools/Mcd.1'\"
  115. else
  116. echo shar: Extracting \"'mtools/Mcd.1'\" \(893 characters\)
  117. sed "s/^X//" >'mtools/Mcd.1' <<'END_OF_FILE'
  118. X.TH MCD 1 local
  119. X.SH NAME
  120. Xmcd \- change MSDOS directory
  121. X.SH SYNOPSIS
  122. X.B mcd
  123. X[ msdosdirectory ]
  124. X.SH DESCRIPTION
  125. XWithout arguments,
  126. X.I mcd
  127. Xwill report the current device and working directory.  Otherwise,
  128. X.I mcd
  129. Xchanges the current device and current working directory relative to an
  130. XMSDOS filesystem.
  131. X.PP
  132. XThe environmental variable MCWD may be used to locate the file where the
  133. Xdevice and current working directory information is stored.  The default
  134. Xis '$HOME/.mcwd'.  Information in this file is ignored if the file is
  135. Xmore than 6 hours old.
  136. X.PP
  137. XMSDOS subdirectory names are supported with either the '/' or '\e\'
  138. Xseparator.  The use of the '\e\' separator or wildcards will require the
  139. Xdirectory name to be enclosed in quotes to protect it from the shell.
  140. X.SH SEE ALSO
  141. Xmdir(1)
  142. X.SH BUGS
  143. XMSDOS doesn't use CD to change to another device.
  144. X.PP
  145. XIt may be wise to remove old .mcwd files at logout.
  146. END_OF_FILE
  147. if test 893 -ne `wc -c <'mtools/Mcd.1'`; then
  148.     echo shar: \"'mtools/Mcd.1'\" unpacked with wrong size!
  149. fi
  150. # end of 'mtools/Mcd.1'
  151. fi
  152. if test -f 'mtools/Mcopy.1' -a "${1}" != "-c" ; then 
  153.   echo shar: Will not clobber existing file \"'mtools/Mcopy.1'\"
  154. else
  155. echo shar: Extracting \"'mtools/Mcopy.1'\" \(1658 characters\)
  156. sed "s/^X//" >'mtools/Mcopy.1' <<'END_OF_FILE'
  157. X.TH MCOPY 1 local
  158. X.SH NAME
  159. Xmcopy \- copy MSDOS files to/from Unix
  160. X.SH SYNOPSIS
  161. X.B mcopy
  162. X[
  163. X.B -tnvm
  164. X] sourcefile targetfile
  165. X.PP
  166. X.B mcopy
  167. X[
  168. X.B -tnvm
  169. X] sourcefile [ sourcefiles... ] targetdirectory
  170. X.SH DESCRIPTION
  171. X.I Mcopy
  172. Xcopies the specified file to the named file, or copies multiple files to
  173. Xthe named directory.  The source and target can be either MSDOS or Unix
  174. Xfiles.
  175. X.PP
  176. XThe use of a drive letter designation on the MSDOS files, 'a:' for
  177. Xexample, determines the direction of the transfer.  A missing drive
  178. Xdesignation implies a Unix file whose path starts in the current
  179. Xdirectory
  180. X.PP
  181. X.I Mcopy
  182. Xwill allow the following command line options:
  183. X.TP
  184. X.B t
  185. XText file transfer.
  186. X.I Mcopy
  187. Xwill translate incoming carriage return/line feeds to line feeds.
  188. X.TP
  189. X.B n
  190. XNo warning.
  191. X.I Mcopy
  192. Xwill not warn the user when overwriting an existing file.
  193. X.TP
  194. X.B v
  195. XVerbose mode.
  196. X.TP
  197. X.B m
  198. XPreserve the file modification time.
  199. X.PP
  200. XIf the target file already exists, and the
  201. X.I -n
  202. Xoption is not in effect,
  203. X.I mcopy
  204. Xasks whether or not to overwrite the file.
  205. X.PP
  206. XMSDOS subdirectory names are supported with either the '/' or '\e\'
  207. Xseparator.  The use of the '\e\' separator or wildcards will require the
  208. Xnames to be enclosed in quotes to protect them from the shell.
  209. X.PP
  210. XThe
  211. X.I mcd
  212. Xcommand may be used to establish the device and the current working
  213. Xdirectory (relative to MSDOS), otherwise the default is A:/.
  214. X.SH SEE ALSO
  215. Xmcd(1), mread(1), mwrite(1)
  216. X.SH BUGS
  217. XUnlike MSDOS, the destination directory may
  218. X.B not
  219. Xbe omitted.
  220. X.PP
  221. XThe '+' operator (append) from MSDOS is not supported.
  222. X.PP
  223. XNo other
  224. X.I Mtools
  225. Xcommand
  226. X.B requires
  227. Xthe use of a drive letter designation on MSDOS files.
  228. END_OF_FILE
  229. if test 1658 -ne `wc -c <'mtools/Mcopy.1'`; then
  230.     echo shar: \"'mtools/Mcopy.1'\" unpacked with wrong size!
  231. fi
  232. # end of 'mtools/Mcopy.1'
  233. fi
  234. if test -f 'mtools/Mdel.1' -a "${1}" != "-c" ; then 
  235.   echo shar: Will not clobber existing file \"'mtools/Mdel.1'\"
  236. else
  237. echo shar: Extracting \"'mtools/Mdel.1'\" \(829 characters\)
  238. sed "s/^X//" >'mtools/Mdel.1' <<'END_OF_FILE'
  239. X.TH MDEL 1 local
  240. X.SH NAME
  241. Xmdel \- delete an MSDOS file
  242. X.SH SYNOPSIS
  243. X.B mdel
  244. X[
  245. X.B -v
  246. X] msdosfile [ msdosfiles...  ]
  247. X.SH DESCRIPTION
  248. X.I Mdel
  249. Xdeletes a file on an MSDOS filesystem.
  250. X.PP
  251. X.I Mdel
  252. Xwill allow the following command line option:
  253. X.TP
  254. X.B v
  255. XVerbose mode.  Echo the filenames as they are processed.
  256. X.PP
  257. X.I Mdel
  258. Xwill ask for verification prior to removing a read\-only file.
  259. X.PP
  260. XMSDOS subdirectory names are supported with either the '/' or '\e\'
  261. Xseparator.  The use of the '\e\' separator or wildcards will require the
  262. Xnames to be enclosed in quotes to protect them from the shell.
  263. X.PP
  264. XThe
  265. X.I mcd
  266. Xcommand may be used to establish the device and the current working
  267. Xdirectory (relative to MSDOS), otherwise the default is A:/.
  268. X.SH SEE ALSO
  269. Xmcd(1)
  270. X.SH BUGS
  271. XAllows multiple arguments, which does not follow the MSDOS convention.
  272. END_OF_FILE
  273. if test 829 -ne `wc -c <'mtools/Mdel.1'`; then
  274.     echo shar: \"'mtools/Mdel.1'\" unpacked with wrong size!
  275. fi
  276. # end of 'mtools/Mdel.1'
  277. fi
  278. if test -f 'mtools/Mdir.1' -a "${1}" != "-c" ; then 
  279.   echo shar: Will not clobber existing file \"'mtools/Mdir.1'\"
  280. else
  281. echo shar: Extracting \"'mtools/Mdir.1'\" \(967 characters\)
  282. sed "s/^X//" >'mtools/Mdir.1' <<'END_OF_FILE'
  283. X.TH MDIR 1 local
  284. X.SH NAME
  285. Xmdir \- display an MSDOS directory
  286. X.SH SYNOPSIS
  287. X.B mdir
  288. X[
  289. X.B -w
  290. X] msdosdirectory
  291. X.PP
  292. X.B mdir
  293. X[
  294. X.B -w
  295. X] msdosfile [ msdosfiles...  ] 
  296. X.SH DESCRIPTION
  297. X.I Mdir
  298. Xdisplays the contents of an MSDOS directory.
  299. X.PP
  300. X.I Mdir
  301. Xwill allow the following command line option:
  302. X.TP
  303. X.B w
  304. XWide output.  This option will print the filenames across the page
  305. Xwithout displaying the file size or creation date.
  306. X.PP
  307. XAn error occurs if a component of the path is not a directory.
  308. X.PP
  309. XMSDOS subdirectory names are supported with either the '/' or '\e\'
  310. Xseparator.  The use of the '\e\' separator or wildcards will require the
  311. Xnames to be enclosed in quotes to protect them from the shell.
  312. X.PP
  313. XThe
  314. X.I mcd
  315. Xcommand may be used to establish the device and the current working
  316. Xdirectory (relative to MSDOS), otherwise the default is A:/.
  317. X.SH SEE ALSO
  318. Xmcd(1)
  319. X.SH BUGS
  320. XAllows multiple arguments, which does not follow the MSDOS convention.
  321. X.PP
  322. XThere is no /P (pause) option.
  323. END_OF_FILE
  324. if test 967 -ne `wc -c <'mtools/Mdir.1'`; then
  325.     echo shar: \"'mtools/Mdir.1'\" unpacked with wrong size!
  326. fi
  327. # end of 'mtools/Mdir.1'
  328. fi
  329. if test -f 'mtools/Mformat.1' -a "${1}" != "-c" ; then 
  330.   echo shar: Will not clobber existing file \"'mtools/Mformat.1'\"
  331. else
  332. echo shar: Extracting \"'mtools/Mformat.1'\" \(865 characters\)
  333. sed "s/^X//" >'mtools/Mformat.1' <<'END_OF_FILE'
  334. X.TH MFORMAT 1 local
  335. X.SH NAME
  336. Xmformat \- add an MSDOS filesystem to a low-level formatted diskette.
  337. X.SH SYNOPSIS
  338. X.B mformat
  339. X[
  340. X.B -t
  341. Xtracks ] [
  342. X.B -h
  343. Xheads ] [
  344. X.B -s
  345. Xsectors ] [
  346. X.B -l
  347. Xvolume label ] drive:
  348. X.SH DESCRIPTION
  349. X.I Mformat
  350. Xadds a minimal MSDOS filesystem (boot sector, FAT, and root directory) to
  351. Xa diskette that has already been formatted by a Unix low-level format.
  352. X.PP
  353. XThe follow options are supported:
  354. X.TP
  355. X.B t
  356. XThe number of tracks (not cylinders).
  357. X.TP
  358. X.B h
  359. XThe number of heads (sides).
  360. X.TP
  361. X.B s
  362. XThe number of sectors per track.
  363. X.TP
  364. X.B l
  365. XAn optional volume label.
  366. X.PP
  367. XTo format a diskette at a density other than the default, you must supply
  368. X(at least) those command line parameters that are different from the
  369. Xdefault.
  370. X.SH SEE ALSO
  371. Xmlabel(1)
  372. X.SH BUGS
  373. XRequires a low-level format utility from Unix.
  374. X.PP
  375. XDoesn't detect (or record) bad block information.
  376. END_OF_FILE
  377. if test 865 -ne `wc -c <'mtools/Mformat.1'`; then
  378.     echo shar: \"'mtools/Mformat.1'\" unpacked with wrong size!
  379. fi
  380. # end of 'mtools/Mformat.1'
  381. fi
  382. if test -f 'mtools/Mkmanifest.1' -a "${1}" != "-c" ; then 
  383.   echo shar: Will not clobber existing file \"'mtools/Mkmanifest.1'\"
  384. else
  385. echo shar: Extracting \"'mtools/Mkmanifest.1'\" \(1570 characters\)
  386. sed "s/^X//" >'mtools/Mkmanifest.1' <<'END_OF_FILE'
  387. X.TH MKMANIFEST 1 local
  388. X.SH NAME
  389. Xmkmanifest \- create a shell script to restore Unix filenames
  390. X.SH SYNOPSIS
  391. X.B mkmanifest
  392. X[ files ]
  393. X.SH DESCRIPTION
  394. X.I Mkmanifest
  395. Xcreates a shell script that will aid in the restoration of Unix filenames
  396. Xthat got clobbered by the MSDOS filename restrictions.  MSDOS filenames
  397. Xare restricted to 8 character names, 3 character extensions, upper case
  398. Xonly, no device names, and no illegal characters.
  399. X.PP
  400. XThe mkmanifest program is compatible with the methods used in
  401. X.I pcomm, arc,
  402. Xand
  403. X.I mtools
  404. Xto change perfectly good Unix filenames to fit the MSDOS restrictions.
  405. X.SH EXAMPLE
  406. XI want to copy the following Unix files to a MSDOS diskette (using the
  407. X.I mcopy
  408. Xcommand).
  409. X.PP
  410. X.in +0.5i
  411. X.nf
  412. Xvery_long_name
  413. X2.many.dots
  414. Xillegal:
  415. Xgood.c
  416. Xprn.dev
  417. XCapital
  418. X.fi
  419. X.in
  420. X.PP
  421. X.I Mcopy
  422. Xwill convert the names to:
  423. X.PP
  424. X.in +0.5i
  425. X.nf
  426. Xvery_lon
  427. X2xmany.dot
  428. Xillegalx
  429. Xgood.c
  430. Xxprn.dev
  431. Xcapital
  432. X.fi
  433. X.in
  434. X.PP
  435. XThe command:
  436. X.PP
  437. Xmkmanifest very_long_name 2.many.dots illegal: good.c prn.dev Capital >
  438. Xmanifest
  439. X.PP
  440. Xwould produce the following:
  441. X.PP
  442. X.in +0.5i
  443. X.nf
  444. Xmv very_lon very_long_name
  445. Xmv 2xmany.dot 2.many.dots
  446. Xmv illegalx illegal:
  447. Xmv xprn.dev prn.dev
  448. Xmv capital Capital
  449. X.fi
  450. X.in
  451. X.PP
  452. XNotice that "good.c" did not require any conversion, so it did not appear
  453. Xin the output.
  454. X.PP
  455. XSuppose I've copied these files from the diskette to another Unix
  456. Xsystem, and I now want the files back to their original names.  If the
  457. Xfile "manifest" (the output captured above) was sent along with those
  458. Xfiles, it could be used to convert the filenames.
  459. X.SH SEE ALSO
  460. Xarc(1), pcomm(1), mtools(1)
  461. END_OF_FILE
  462. if test 1570 -ne `wc -c <'mtools/Mkmanifest.1'`; then
  463.     echo shar: \"'mtools/Mkmanifest.1'\" unpacked with wrong size!
  464. fi
  465. # end of 'mtools/Mkmanifest.1'
  466. fi
  467. if test -f 'mtools/Mlabel.1' -a "${1}" != "-c" ; then 
  468.   echo shar: Will not clobber existing file \"'mtools/Mlabel.1'\"
  469. else
  470. echo shar: Extracting \"'mtools/Mlabel.1'\" \(649 characters\)
  471. sed "s/^X//" >'mtools/Mlabel.1' <<'END_OF_FILE'
  472. X.TH MLABEL 1 local
  473. X.SH NAME
  474. Xmlabel \- make an MSDOS volume label
  475. X.SH SYNOPSIS
  476. X.B mlabel
  477. X[
  478. X.B -v
  479. X] drive:
  480. X.SH DESCRIPTION
  481. X.I Mlabel
  482. Xdisplays the current volume label, if present, and prompts the user
  483. Xfor a new volume label.  To delete an existing volume label, press
  484. Xreturn at the prompt.
  485. X.PP
  486. X.I Mlabel
  487. Xwill allow the following command line option:
  488. X.TP
  489. X.B v
  490. XVerbose mode.  Display the new volume label if the label supplied is
  491. Xinvalid.
  492. X.PP
  493. XReasonable care is taken to create a valid MSDOS volume label.  If an
  494. Xinvalid label is specified,
  495. X.I mlabel
  496. Xwill change the label (and display the new label if the verbose mode is
  497. Xset).
  498. X.SH SEE ALSO
  499. Xmformat(1)
  500. END_OF_FILE
  501. if test 649 -ne `wc -c <'mtools/Mlabel.1'`; then
  502.     echo shar: \"'mtools/Mlabel.1'\" unpacked with wrong size!
  503. fi
  504. # end of 'mtools/Mlabel.1'
  505. fi
  506. if test -f 'mtools/Mmd.1' -a "${1}" != "-c" ; then 
  507.   echo shar: Will not clobber existing file \"'mtools/Mmd.1'\"
  508. else
  509. echo shar: Extracting \"'mtools/Mmd.1'\" \(1048 characters\)
  510. sed "s/^X//" >'mtools/Mmd.1' <<'END_OF_FILE'
  511. X.TH MMD 1 local
  512. X.SH NAME
  513. Xmmd \- make an MSDOS subdirectory
  514. X.SH SYNOPSIS
  515. X.B mmd
  516. X[
  517. X.B -v
  518. X] msdosdirectory [ msdosdirectories... ]
  519. X.SH DESCRIPTION
  520. X.I Mmd
  521. Xmakes a new directory on an MSDOS filesystem.
  522. X.PP
  523. X.I Mmd
  524. Xwill allow the following command line option:
  525. X.TP
  526. X.B v
  527. XVerbose mode.  Display the new directory name if the name supplied is
  528. Xinvalid.
  529. X.PP
  530. XReasonable care is taken to create a valid MSDOS directory name.  If an
  531. Xinvalid name is specified,
  532. X.I mmd
  533. Xwill change the name (and display the new name if the verbose mode is
  534. Xset).
  535. X.PP
  536. XAn error occurs if the directory already exists.
  537. X.PP
  538. XMSDOS subdirectory names are supported with either the '/' or '\e\'
  539. Xseparator.  The use of the '\e\' separator or wildcards will require the
  540. Xdirectory name to be enclosed in quotes to protect it from the shell.
  541. X.PP
  542. XThe
  543. X.I mcd
  544. Xcommand may be used to establish the device and the current working
  545. Xdirectory (relative to MSDOS), otherwise the default is A:/.
  546. X.SH SEE ALSO
  547. Xmcd(1), mrd(1)
  548. X.SH BUGS
  549. XAllows multiple arguments, which does not follow the MSDOS convention.
  550. END_OF_FILE
  551. if test 1048 -ne `wc -c <'mtools/Mmd.1'`; then
  552.     echo shar: \"'mtools/Mmd.1'\" unpacked with wrong size!
  553. fi
  554. # end of 'mtools/Mmd.1'
  555. fi
  556. if test -f 'mtools/Mrd.1' -a "${1}" != "-c" ; then 
  557.   echo shar: Will not clobber existing file \"'mtools/Mrd.1'\"
  558. else
  559. echo shar: Extracting \"'mtools/Mrd.1'\" \(707 characters\)
  560. sed "s/^X//" >'mtools/Mrd.1' <<'END_OF_FILE'
  561. X.TH MRD 1 local
  562. X.SH NAME
  563. Xmrd \- remove an MSDOS subdirectory
  564. X.SH SYNOPSIS
  565. X.B mrd
  566. Xmsdosdirectory [ msdosdirectories... ]
  567. X.SH DESCRIPTION
  568. X.I Mrd
  569. Xremoves a directory from an MSDOS filesystem.
  570. X.PP
  571. XAn error occurs if the directory is not empty.
  572. X.PP
  573. XMSDOS subdirectory names are supported with either the '/' or '\e\'
  574. Xseparator.  The use of the '\e\' separator or wildcards will require the
  575. Xdirectory name to be enclosed in quotes to protect it from the shell.
  576. X.PP
  577. XThe
  578. X.I mcd
  579. Xcommand may be used to establish the device and the current working
  580. Xdirectory (relative to MSDOS), otherwise the default is A:/.
  581. X.SH SEE ALSO
  582. Xmcd(1), mmd(1)
  583. X.SH BUGS
  584. XAllows multiple arguments, which does not follow the MSDOS convention.
  585. END_OF_FILE
  586. if test 707 -ne `wc -c <'mtools/Mrd.1'`; then
  587.     echo shar: \"'mtools/Mrd.1'\" unpacked with wrong size!
  588. fi
  589. # end of 'mtools/Mrd.1'
  590. fi
  591. if test -f 'mtools/Mread.1' -a "${1}" != "-c" ; then 
  592.   echo shar: Will not clobber existing file \"'mtools/Mread.1'\"
  593. else
  594. echo shar: Extracting \"'mtools/Mread.1'\" \(1293 characters\)
  595. sed "s/^X//" >'mtools/Mread.1' <<'END_OF_FILE'
  596. X.TH MREAD 1 local
  597. X.SH NAME
  598. Xmread \- low level read (copy) an MSDOS file to Unix
  599. X.SH SYNOPSIS
  600. X.B mread
  601. X[
  602. X.B -tnm
  603. X] msdosfile unixfile
  604. X.PP
  605. X.B mread
  606. X[
  607. X.B -tnm
  608. X] msdosfile [ msdosfiles... ] unixdirectory
  609. X.SH DESCRIPTION
  610. XIn the first form,
  611. X.I mread
  612. Xcopies the specified MSDOS file to the named Unix file.  The second form
  613. Xof the command copies multiple MSDOS files to the named Unix directory.
  614. X.PP
  615. X.I Mread
  616. Xwill allow the following command line options:
  617. X.TP
  618. X.B t
  619. XText file transfer.
  620. X.I Mread
  621. Xwill translate incoming carriage return/line feeds to line feeds.
  622. X.TP
  623. X.B n
  624. XNo warning.
  625. X.I Mread
  626. Xwill not warn the user when overwriting an existing file.
  627. X.TP
  628. X.B m
  629. XPreserve the file modification times.
  630. X.PP
  631. XIf the target file already exists, and the
  632. X.I -n
  633. Xoption is not in effect,
  634. X.I mread
  635. Xasks whether or not to overwrite the file.
  636. X.PP
  637. XMSDOS subdirectory names are supported with either the '/' or '\e\'
  638. Xseparator.  The use of the '\e\' separator or wildcards will require the
  639. Xnames to be enclosed in quotes to protect them from the shell.
  640. X.PP
  641. XThe
  642. X.I mcd
  643. Xcommand may be used to establish the device and the current working
  644. Xdirectory (relative to MSDOS), otherwise the default is A:/.
  645. X.SH SEE ALSO
  646. Xmcd(1), mcopy(1), mtype(1), mwrite(1)
  647. X.SH BUGS
  648. XUnlike MSDOS, the destination directory may
  649. X.B not
  650. Xbe omitted.
  651. END_OF_FILE
  652. if test 1293 -ne `wc -c <'mtools/Mread.1'`; then
  653.     echo shar: \"'mtools/Mread.1'\" unpacked with wrong size!
  654. fi
  655. # end of 'mtools/Mread.1'
  656. fi
  657. if test -f 'mtools/Mren.1' -a "${1}" != "-c" ; then 
  658.   echo shar: Will not clobber existing file \"'mtools/Mren.1'\"
  659. else
  660. echo shar: Extracting \"'mtools/Mren.1'\" \(1186 characters\)
  661. sed "s/^X//" >'mtools/Mren.1' <<'END_OF_FILE'
  662. X.TH MREN 1 local
  663. X.SH NAME
  664. Xmren \- rename an existing MSDOS file
  665. X.SH SYNOPSIS
  666. X.B mren
  667. X[
  668. X.B -v
  669. X] sourcefile targetfile
  670. X.SH DESCRIPTION
  671. X.I Mren
  672. Xrenames an existing file on an MSDOS filesystem.
  673. X.PP
  674. X.I Mren
  675. Xwill allow the following command line option:
  676. X.TP
  677. X.B v
  678. XVerbose mode.  Display the new filename if the name supplied is
  679. Xinvalid.
  680. X.PP
  681. XReasonable care is taken to create a valid MSDOS filename.  If an invalid
  682. XMSDOS target name is specified,
  683. X.I mren
  684. Xwill change the name (and prompt the user to accept or reject the new name
  685. Xif the verbose mode is set).
  686. X.PP
  687. XThe path component of the target filename (if supplied) is ignored.  In
  688. Xother words, you may not use
  689. X.I mren
  690. Xto move a file from one subdirectory to another.
  691. X.PP 
  692. X.I Mren
  693. Xmay be used to rename directories.
  694. X.PP
  695. XMSDOS subdirectory names are supported with either the '/' or '\e\'
  696. Xseparator.  The use of the '\e\' separator or wildcards will require the
  697. Xnames to be enclosed in quotes to protect them from the shell.
  698. X.PP
  699. XThe
  700. X.I mcd
  701. Xcommand may be used to establish the device and the current working
  702. Xdirectory (relative to MSDOS), otherwise the default is A:/.
  703. X.SH SEE ALSO
  704. Xmcd(1)
  705. X.SH BUGS
  706. XMSDOS can't use REN to rename directories.
  707. END_OF_FILE
  708. if test 1186 -ne `wc -c <'mtools/Mren.1'`; then
  709.     echo shar: \"'mtools/Mren.1'\" unpacked with wrong size!
  710. fi
  711. # end of 'mtools/Mren.1'
  712. fi
  713. if test -f 'mtools/Mtools.1' -a "${1}" != "-c" ; then 
  714.   echo shar: Will not clobber existing file \"'mtools/Mtools.1'\"
  715. else
  716. echo shar: Extracting \"'mtools/Mtools.1'\" \(2116 characters\)
  717. sed "s/^X//" >'mtools/Mtools.1' <<'END_OF_FILE'
  718. X.TH MTOOLS 1 local
  719. X.SH NAME
  720. XMtools \- a collection of tools for manipulating MSDOS files
  721. X.SH SYNOPSIS
  722. X.nf
  723. X\fBmattrib\fR \- change MSDOS file attribute flags
  724. X\fBmcd\fR \- change MSDOS directory
  725. X\fBmcopy\fR \- copy MSDOS files to/from Unix
  726. X\fBmdel\fR \- delete an MSDOS file
  727. X\fBmdir\fR \- display an MSDOS directory
  728. X\fBmformat\fR \- add an MSDOS filesystem to a low-level formatted diskette
  729. X\fBmlabel\fR \- make an MSDOS volume label
  730. X\fBmmd\fR \- make an MSDOS subdirectory
  731. X\fBmrd\fR \- remove an MSDOS subdirectory
  732. X\fBmread\fR \- low level read (copy) an MSDOS file to Unix
  733. X\fBmren\fR \- rename an existing MSDOS file
  734. X\fBmtype\fR \- display contents of an MSDOS file
  735. X\fBmwrite\fR \- low level write (copy) a Unix file to MSDOS
  736. X.fi
  737. X.SH DESCRIPTION
  738. XMtools is a public domain collection of programs to allow Unix systems
  739. Xto read, write, and manipulate files on an MSDOS filesystem (typically a
  740. Xdiskette).  Each program attempts to emulate the MSDOS equivalent
  741. Xcommand as closely as practical.
  742. X.PP
  743. XMSDOS filenames are optionally composed of a drive letter followed by a
  744. Xcolon, a subdirectory, and a filename.  Subdirectory names can use either
  745. Xthe '/' or '\e\' separator.  The use of the '\e\' separator or wildcards
  746. Xwill require the names to be enclosed in quotes to protect them from the
  747. Xshell.
  748. X.PP
  749. XThe regular expression "pattern matching" routines follow the Unix-style
  750. Xrules.  For example, '*' matches all MSDOS files in lieu of '*.*'.  The
  751. Xarchive, hidden, read-only and system attribute bits are ignored during
  752. Xpattern matching.
  753. X.PP
  754. XAll options use the '-' (minus) flag, not '/' as you'd expect in MSDOS.
  755. X.PP
  756. XThe
  757. X.I mcd
  758. Xcommand is used to establish the device and the current working
  759. Xdirectory (relative to the MSDOS filesystem), otherwise the default is
  760. Xassumed to be A:/.
  761. X.SH SEE ALSO
  762. Xmattrib(1), mcd(1), mdel(1), mformat(1), mrd(1), mren(1), mtype(1),
  763. Xmcopy(1), mdir(1), mlabel(1), mmd(1), mread(1), mwrite(1)
  764. X.SH BUGS
  765. XAn unfortunate side effect of not guessing the proper device (when
  766. Xmultiple disk capacities are supported) is an occasional error message
  767. Xfrom the device driver.  These can be safely ignored.
  768. END_OF_FILE
  769. if test 2116 -ne `wc -c <'mtools/Mtools.1'`; then
  770.     echo shar: \"'mtools/Mtools.1'\" unpacked with wrong size!
  771. fi
  772. # end of 'mtools/Mtools.1'
  773. fi
  774. if test -f 'mtools/Mtype.1' -a "${1}" != "-c" ; then 
  775.   echo shar: Will not clobber existing file \"'mtools/Mtype.1'\"
  776. else
  777. echo shar: Extracting \"'mtools/Mtype.1'\" \(903 characters\)
  778. sed "s/^X//" >'mtools/Mtype.1' <<'END_OF_FILE'
  779. X.TH MTYPE 1 local
  780. X.SH NAME
  781. Xmtype \- display contents of an MSDOS file
  782. X.SH SYNOPSIS
  783. X.B mtype
  784. X[
  785. X.B -ts
  786. X] msdosfile [ msdosfiles... ]
  787. X.SH DESCRIPTION
  788. X.I Mtype
  789. Xdisplays the specified MSDOS file on the screen.
  790. X.PP
  791. X.I Mtype
  792. Xwill allow the following command line options:
  793. X.TP
  794. X.B t
  795. XText file viewing.
  796. X.I Mtype
  797. Xwill translate incoming carriage return/line feeds to line feeds.
  798. X.TP
  799. X.B s
  800. XStrip high bit.
  801. X.I Mtype
  802. Xwill strip the high bit from the data.
  803. X.PP
  804. XMSDOS subdirectory names are supported with either the '/' or '\e\'
  805. Xseparator.  The use of the '\e\' separator or wildcards will require the
  806. Xnames to be enclosed in quotes to protect them from the shell.
  807. X.PP
  808. XThe
  809. X.I mcd
  810. Xcommand may be used to establish the device and the current working
  811. Xdirectory (relative to MSDOS), otherwise the default is A:/.
  812. X.SH SEE ALSO
  813. Xmcd(1), mread(1)
  814. X.SH BUGS
  815. XAllows multiple arguments, which does not follow the MSDOS convention.
  816. END_OF_FILE
  817. if test 903 -ne `wc -c <'mtools/Mtype.1'`; then
  818.     echo shar: \"'mtools/Mtype.1'\" unpacked with wrong size!
  819. fi
  820. # end of 'mtools/Mtype.1'
  821. fi
  822. if test -f 'mtools/Mwrite.1' -a "${1}" != "-c" ; then 
  823.   echo shar: Will not clobber existing file \"'mtools/Mwrite.1'\"
  824. else
  825. echo shar: Extracting \"'mtools/Mwrite.1'\" \(1570 characters\)
  826. sed "s/^X//" >'mtools/Mwrite.1' <<'END_OF_FILE'
  827. X.TH MWRITE 1 local
  828. X.SH NAME
  829. Xmwrite \- low level write (copy) a Unix file to MSDOS
  830. X.SH SYNOPSIS
  831. X.B mwrite
  832. X[
  833. X.B -tnvm
  834. X] unixfile msdosfile
  835. X.PP
  836. X.B mwrite
  837. X[
  838. X.B -tnvm
  839. X] unixfile [ unixfiles... ] msdosdirectory
  840. X.SH DESCRIPTION
  841. XIn the first form,
  842. X.I mwrite
  843. Xcopies the specified Unix file to the named MSDOS file.  The second form
  844. Xof the command copies multiple Unix files to the named MSDOS directory.
  845. X.PP
  846. X.I Mwrite
  847. Xwill allow the following command line options:
  848. X.TP
  849. X.B t
  850. XText file transfer.
  851. X.I Mwrite
  852. Xwill translate incoming line feeds to carriage return/line feeds.
  853. X.TP
  854. X.B n
  855. XNo warning.
  856. X.I Mwrite
  857. Xwill not warn the user when overwriting an existing file.
  858. X.TP
  859. X.B v
  860. XVerbose mode.  Display the new filename if the Unix filename requires
  861. Xconversion.
  862. X.TP
  863. X.B m
  864. XPreserve the file modification times.
  865. X.PP
  866. XIf the target file already exists, and the
  867. X.I -n
  868. Xoption is not in effect,
  869. X.I mwrite
  870. Xasks whether or not to overwrite the file.
  871. X.PP
  872. XReasonable care is taken to create a valid MSDOS filename.  If an
  873. Xinvalid name is specified,
  874. X.I mwrite
  875. Xwill change the name (and display the new name if the verbose mode is
  876. Xset).
  877. X.PP
  878. XMSDOS subdirectory names are are supported with either the '/' or '\e\'
  879. Xseparator.  The use of the '\e\' separator or wildcards will require the
  880. Xnames to be enclosed in quotes to protect them from the shell.
  881. X.PP
  882. XThe
  883. X.I mcd
  884. Xcommand may be used to establish the device and the current working
  885. Xdirectory (relative to MSDOS), otherwise the default is A:/.
  886. X.SH SEE ALSO
  887. Xmcd(1), mcopy(1), mread(1)
  888. X.SH BUGS
  889. XUnlike MSDOS, the destination directory may
  890. X.B not
  891. Xbe omitted.
  892. END_OF_FILE
  893. if test 1570 -ne `wc -c <'mtools/Mwrite.1'`; then
  894.     echo shar: \"'mtools/Mwrite.1'\" unpacked with wrong size!
  895. fi
  896. # end of 'mtools/Mwrite.1'
  897. fi
  898. if test -f 'mtools/Readme' -a "${1}" != "-c" ; then 
  899.   echo shar: Will not clobber existing file \"'mtools/Readme'\"
  900. else
  901. echo shar: Extracting \"'mtools/Readme'\" \(2533 characters\)
  902. sed "s/^X//" >'mtools/Readme' <<'END_OF_FILE'
  903. X                MTOOLS
  904. X                  version 2.0
  905. X
  906. XMtools is a public domain collection of programs to allow Unix systems
  907. Xto read, write, and manipulate files on an MSDOS filesystem (typically a
  908. Xdiskette).
  909. X
  910. XThe following MSDOS commands are emulated:
  911. X
  912. XMtool         MSDOS
  913. Xname        equivalent    Description
  914. X-----        ----        -----------
  915. Xmattrib        ATTRIB        change MSDOS file attribute flags
  916. Xmcd        CD        change MSDOS directory
  917. Xmcopy        COPY        copy MSDOS files to/from Unix
  918. Xmdel        DEL/ERASE    delete an MSDOS file
  919. Xmdir        DIR        display an MSDOS directory
  920. Xmformat        FORMAT        add MSDOS filesystem to a low-level format
  921. Xmlabel        LABEL        make an MSDOS volume label.
  922. Xmmd        MD/MKDIR    make an MSDOS subdirectory
  923. Xmrd        RD/RMDIR    remove an MSDOS subdirectory
  924. Xmread        COPY        low level read (copy) an MSDOS file to Unix
  925. Xmren        REN/RENAME    rename an existing MSDOS file
  926. Xmtype        TYPE        display contents of an MSDOS file
  927. Xmwrite        COPY        low level write (copy) a Unix file to MSDOS
  928. X
  929. XYou should be able to just close your eyes and pretend you're on an MSDOS
  930. Xsystem.  Everything should work the same... except for the added 'm' at
  931. Xthe beginning of each command.
  932. X
  933. XI really wanted to avoid the use of a 'text' mode and a 'data' mode when
  934. Xtransferring files, but I couldn't find a better way.  It gets rather
  935. Xconfusing and it's quite possible to mess up a file if you apply the
  936. Xtext mode when it is not appropriate (ie:  to a COM or EXE file).
  937. X
  938. XThe pattern matching routine more closely resembles Unix than MSDOS.
  939. XFor example, "*" matches all MSDOS files in lieu of "*.*".
  940. X
  941. XThe use of wildcards (or the '\' separator) will require the names to be
  942. Xenclosed in quotes to protect them from the shell.  For example:
  943. X
  944. X    RIGHT:    mcopy "a:*.c" .
  945. X
  946. X    will copy all files on the A: disk with the extension .C to the
  947. X    current Unix directory.
  948. X
  949. X    WRONG:    mcopy a:*.c .
  950. X
  951. X    will cause the shell to expand a:*.c in the current Unix directory
  952. X    (which is probably not what you wanted) then copy that list of
  953. X    files (if there were any) from A: to the current Unix directory.
  954. X
  955. X    RIGHT:    mcopy *.c a:
  956. X
  957. X    will copy all files with the extension .c in the current Unix
  958. X    directory to the A: drive.  (This time you *want* the shell
  959. X    the expand the *.c).
  960. X
  961. XThe manuals are very terse...  it's assumed that the reader is already
  962. Xfamiliar with MSDOS.
  963. X
  964. XMcopy is really a front-end to the low level Mread and Mwrite commands.
  965. X
  966. XEmmet P. Gray                US Army, HQ III Corps & Fort Hood
  967. X...!uunet!uiucuxc!fthood!egray        Attn: AFZF-DE-ENV
  968. Xfthood!egray@uxc.cso.uiuc.edu        Directorate of Engineering & Housing
  969. X                    Environmental Management Office
  970. X                    Fort Hood, TX 76544-5057
  971. END_OF_FILE
  972. if test 2533 -ne `wc -c <'mtools/Readme'`; then
  973.     echo shar: \"'mtools/Readme'\" unpacked with wrong size!
  974. fi
  975. # end of 'mtools/Readme'
  976. fi
  977. if test -f 'mtools/Release.notes' -a "${1}" != "-c" ; then 
  978.   echo shar: Will not clobber existing file \"'mtools/Release.notes'\"
  979. else
  980. echo shar: Extracting \"'mtools/Release.notes'\" \(1008 characters\)
  981. sed "s/^X//" >'mtools/Release.notes' <<'END_OF_FILE'
  982. XNew in the v2.0 release....
  983. X
  984. X    1) Support for multiple devices.  Mtools now supports:
  985. X        multiple floppy disks (A:, B:, etc)
  986. X        DOS partitions on a hard disk
  987. X        DOS "images" such as those VP/ix uses.
  988. X
  989. X    2) Wildcards are supported anywhere in a pathname (not just
  990. X    in the "filename" part as before)
  991. X
  992. X    3) Reads and writes to slow devices are now "cylinder buffered"
  993. X    when appropriate.
  994. X
  995. X    4) Versions of CD, FORMAT, LABEL, and ATTRIB have been added.
  996. X
  997. X    5) A Mtools.1 manual page has beed added for an overview of Mtools.
  998. X
  999. X    6) The mkmanifest command has been added.  Although not an 'mtool'
  1000. X    command, it makes life easier when fixing up Unix filenames that
  1001. X    get clobbered by MSDOS file name restrictions.
  1002. X
  1003. X    7) The mkdfs program of the "fast-mtools" release for the Sun
  1004. X    SparcStation can be replaced with mformat.
  1005. X
  1006. X    8) The Configure file has been included to help those who must add
  1007. X    devices to the devices.c file.
  1008. X
  1009. X    Many thanks to Viktor Dukhovni (viktor@math.princeton.edu) for
  1010. X    many of the ideas in the new release.
  1011. END_OF_FILE
  1012. if test 1008 -ne `wc -c <'mtools/Release.notes'`; then
  1013.     echo shar: \"'mtools/Release.notes'\" unpacked with wrong size!
  1014. fi
  1015. # end of 'mtools/Release.notes'
  1016. fi
  1017. if test -f 'mtools/buf_read.c' -a "${1}" != "-c" ; then 
  1018.   echo shar: Will not clobber existing file \"'mtools/buf_read.c'\"
  1019. else
  1020. echo shar: Extracting \"'mtools/buf_read.c'\" \(1759 characters\)
  1021. sed "s/^X//" >'mtools/buf_read.c' <<'END_OF_FILE'
  1022. X/*
  1023. X * Do full cylinder buffered reads from slow devices.  Uses a simple
  1024. X * buffered read/delayed write algorithm.
  1025. X */
  1026. X
  1027. X#include <stdio.h>
  1028. X#include "msdos.h"
  1029. X
  1030. Xunsigned char *disk_buf;        /* disk read/write buffer */
  1031. Xint disk_size;                /* size of read/write buffer */
  1032. Xlong disk_current;            /* first sector in buffer */
  1033. Xint disk_dirty;                /* is the buffer dirty? */
  1034. X
  1035. Xextern int fd;
  1036. Xextern long disk_offset;
  1037. X
  1038. Xvoid
  1039. Xdisk_read(start, buf, len)
  1040. Xlong start;
  1041. Xunsigned char *buf;
  1042. Xint len;
  1043. X{
  1044. X    register long i;
  1045. X    int length;
  1046. X    unsigned char *buf_ptr, *disk_ptr;
  1047. X    char *memcpy();
  1048. X    long where, tail, lseek();
  1049. X    void perror(), exit(), disk_flush();
  1050. X
  1051. X                    /* don't use cache? */
  1052. X    if (disk_size == 1) {
  1053. X        where = (start * MSECTOR_SIZE) + disk_offset;
  1054. X        if (lseek(fd, where, 0) < 0) {
  1055. X            perror("disk_read: lseek");
  1056. X            exit(1);
  1057. X        }
  1058. X                    /* read it! */
  1059. X        if (read(fd, (char *) buf, (unsigned int) len) != len) {
  1060. X            perror("disk_read: read");
  1061. X            exit(1);
  1062. X        }
  1063. X        return;
  1064. X    }
  1065. X
  1066. X    tail = start + (len / MSECTOR_SIZE) - 1;
  1067. X    for (i = start; i <= tail; i++) {
  1068. X                    /* a "cache" miss */
  1069. X        if (i < disk_current || i >= disk_current + disk_size) {
  1070. X
  1071. X            if (disk_dirty)
  1072. X                disk_flush();
  1073. X
  1074. X            disk_current = (i / disk_size) * disk_size;
  1075. X            where = (disk_current * MSECTOR_SIZE) + disk_offset;
  1076. X            length = disk_size * MSECTOR_SIZE;
  1077. X
  1078. X                    /* move to next location */
  1079. X            if (lseek(fd, where, 0) < 0) {
  1080. X                perror("disk_read: lseek");
  1081. X                exit(1);
  1082. X            }
  1083. X                    /* read it! */
  1084. X            if (read(fd, (char *) disk_buf, (unsigned int) length) != length) {
  1085. X                perror("disk_read: read");
  1086. X                exit(1);
  1087. X            }
  1088. X        }
  1089. X                    /* a cache hit... */
  1090. X        buf_ptr = buf + ((i - start) * MSECTOR_SIZE);
  1091. X        disk_ptr = disk_buf + ((i - disk_current) * MSECTOR_SIZE);
  1092. X        memcpy((char *) buf_ptr, (char *) disk_ptr, MSECTOR_SIZE);
  1093. X    }
  1094. X    return;
  1095. X}
  1096. END_OF_FILE
  1097. if test 1759 -ne `wc -c <'mtools/buf_read.c'`; then
  1098.     echo shar: \"'mtools/buf_read.c'\" unpacked with wrong size!
  1099. fi
  1100. # end of 'mtools/buf_read.c'
  1101. fi
  1102. if test -f 'mtools/devices.c' -a "${1}" != "-c" ; then 
  1103.   echo shar: Will not clobber existing file \"'mtools/devices.c'\"
  1104. else
  1105. echo shar: Extracting \"'mtools/devices.c'\" \(2619 characters\)
  1106. sed "s/^X//" >'mtools/devices.c' <<'END_OF_FILE'
  1107. X/*
  1108. X * Device tables.  See the Configure file for a complete description.
  1109. X */
  1110. X
  1111. X#include <stdio.h>
  1112. X#include "msdos.h"
  1113. X
  1114. X#ifdef DELL
  1115. Xstruct device devices[] = {
  1116. X    {'A', "/dev/rdsk/f0d9dt", 0L, 12, 0, (int (*) ()) 0, 40, 2, 9},
  1117. X    {'A', "/dev/rdsk/f0q15dt", 0L, 12, 0, (int (*) ()) 0, 80, 2, 15},
  1118. X    {'A', "/dev/rdsk/f0d8dt", 0L, 12, 0, (int (*) ()) 0, 40, 2, 8},
  1119. X    {'B', "/dev/rdsk/f13ht", 0L, 12, 0, (int (*) ()) 0, 80, 2, 18},
  1120. X    {'B', "/dev/rdsk/f13dt", 0L, 12, 0, (int (*) ()) 0, 80, 2, 9},
  1121. X    {'C', "/dev/rdsk/dos", 0L, 16, 0, (int (*) ()) 0, 0, 0, 0},
  1122. X    {'\0', (char *) NULL, 0L, 0, 0, (int (*) ()) 0, 0, 0, 0}
  1123. X};
  1124. X#endif /* DELL */
  1125. X
  1126. X#ifdef ISC
  1127. Xstruct device devices[] = {
  1128. X    {'A', "/dev/rdsk/f0d9dt", 0L, 12, 0, (int (*) ()) 0, 40, 2, 9},
  1129. X    {'A', "/dev/rdsk/f0q15dt", 0L, 12, 0, (int (*) ()) 0, 80, 2, 15},
  1130. X    {'A', "/dev/rdsk/f0d8dt", 0L, 12, 0, (int (*) ()) 0, 40, 2, 8},
  1131. X    {'B', "/dev/rdsk/f13ht", 0L, 12, 0, (int (*) ()) 0, 80, 2, 18},
  1132. X    {'B', "/dev/rdsk/f13dt", 0L, 12, 0, (int (*) ()) 0, 80, 2, 9},
  1133. X    {'C', "/dev/rdsk/0p1", 0L, 16, 0, (int (*) ()) 0, 0, 0, 0},
  1134. X    {'D', "/usr/vpix/defaults/C:", 8704L, 12, 0, (int (*) ()) 0, 0, 0, 0},
  1135. X    {'E', "$HOME/vpix/C:", 8704L, 12, 0, (int (*) ()) 0, 0, 0, 0},
  1136. X    {'\0', (char *) NULL, 0L, 0, 0, (int (*) ()) 0, 0, 0, 0}
  1137. X};
  1138. X#endif /* ISC */
  1139. X
  1140. X#ifdef MASSCOMP
  1141. Xstruct device devices[] = {
  1142. X    {'A', "/dev/rflp", 0L, 12, 0, (int (*) ()) 0, 80, 2, 8},
  1143. X    {'\0', (char *) NULL, 0L, 0, 0, (int (*) ()) 0, 0, 0, 0}
  1144. X};
  1145. X#endif /* MASSCOMP */
  1146. X
  1147. X#ifdef SPARC
  1148. Xstruct device devices[] = {
  1149. X    {'A', "/dev/rfd0c", 0L, 12, 0, (int (*) ()) 0, 80, 2, 18},
  1150. X    {'A', "/dev/rfd0c", 0L, 12, 0, (int (*) ()) 0, 80, 2, 9},
  1151. X    {'\0', (char *) NULL, 0L, 0, 0, (int (*) ()) 0, 0, 0, 0}
  1152. X};
  1153. X#endif /* SPARC */
  1154. X
  1155. X#ifdef UNIXPC
  1156. X#include <sys/gdioctl.h>
  1157. X#include <fcntl.h>
  1158. X
  1159. Xint init_unixpc();
  1160. X
  1161. Xstruct device devices[] = {
  1162. X    {'A', "/dev/rfp020", 0L, 12, O_NDELAY, init_unixpc, 40, 2, 9},
  1163. X    {'C', "/usr/bin/DOS/dvd000", 0L, 12, 0, (int (*) ()) 0, 0, 0, 0},
  1164. X    {'\0', (char *) NULL, 0L, 0, 0, (int (*) ()) 0, 0, 0, 0}
  1165. X};
  1166. X
  1167. Xint
  1168. Xinit_unixpc(fd, ntracks, nheads, nsect)
  1169. Xint fd, ntracks, nheads, nsect;
  1170. X{
  1171. X    struct gdctl gdbuf;
  1172. X
  1173. X    if (ioctl(fd, GDGETA, &gdbuf) == -1) {
  1174. X        ioctl(fd, GDDISMNT, &gdbuf);
  1175. X        return(1);
  1176. X    }
  1177. X
  1178. X    gdbuf.params.cyls = ntracks * nheads;
  1179. X    gdbuf.params.heads = nheads;
  1180. X    gdbuf.params.psectrk = nsect;
  1181. X
  1182. X    gdbuf.params.pseccyl = gdbuf.params.psectrk * gdbuf.params.heads;
  1183. X    gdbuf.params.flags = 1;        /* disk type flag */
  1184. X    gdbuf.params.step = 0;        /* step rate for controller */
  1185. X    gdbuf.params.sectorsz = 512;    /* sector size */
  1186. X
  1187. X    if (ioctl(fd, GDSETA, &gdbuf) < 0) {
  1188. X        ioctl(fd, GDDISMNT, &gdbuf);
  1189. X        return(1);
  1190. X    }
  1191. X    return(0);
  1192. X}
  1193. X#endif /* UNIXPC */
  1194. END_OF_FILE
  1195. if test 2619 -ne `wc -c <'mtools/devices.c'`; then
  1196.     echo shar: \"'mtools/devices.c'\" unpacked with wrong size!
  1197. fi
  1198. # end of 'mtools/devices.c'
  1199. fi
  1200. if test -f 'mtools/dir_make.c' -a "${1}" != "-c" ; then 
  1201.   echo shar: Will not clobber existing file \"'mtools/dir_make.c'\"
  1202. else
  1203. echo shar: Extracting \"'mtools/dir_make.c'\" \(2037 characters\)
  1204. sed "s/^X//" >'mtools/dir_make.c' <<'END_OF_FILE'
  1205. X#include <stdio.h>
  1206. X#include <time.h>
  1207. X#include "msdos.h"
  1208. X
  1209. Xextern int dir_start, dir_len, clus_size, dir_entries, fat_error, clus_size;
  1210. Xextern unsigned int num_clus, end_fat, last_fat;
  1211. Xextern long dir_chain[MAX_DIR_SECS];
  1212. Xextern unsigned char *dir_buf;
  1213. X
  1214. X/*
  1215. X * Make a subdirectory grow in length.  Only subdirectories (not root)
  1216. X * may grow.  Returns a 0 on success, 1 on failure (disk full), or -1
  1217. X * on error.
  1218. X */
  1219. X
  1220. Xint
  1221. Xdir_grow(fat)
  1222. Xunsigned int fat;
  1223. X{
  1224. X    int i, num, buflen, new;
  1225. X    long sector;
  1226. X    char *memset(), *realloc();
  1227. X    unsigned char *offset, tbuf[MAX_CLUSTER];
  1228. X    unsigned int next, last, next_fat(), fat_decode();
  1229. X    void perror(), exit(), disk_write(), disk_read();
  1230. X
  1231. X    last = next_fat(0);
  1232. X    if (last == 1)
  1233. X        return(1);
  1234. X
  1235. X    /* CONSTCOND */
  1236. X    while (1) {
  1237. X        next = fat_decode(fat);
  1238. X        if (next == 1) {
  1239. X            fprintf(stderr, "dir_grow: FAT problem\n");
  1240. X            fat_error++;
  1241. X            return(-1);
  1242. X        }
  1243. X                    /* end of cluster chain */
  1244. X        if (next >= last_fat)
  1245. X            break;
  1246. X        fat = next;
  1247. X    }
  1248. X                    /* mark the end of the chain */
  1249. X    fat_encode(fat, last);
  1250. X    fat_encode(last, end_fat);
  1251. X                    /* zero the buffer */
  1252. X    buflen = clus_size * MSECTOR_SIZE;
  1253. X    memset((char *) tbuf, '\0', buflen);
  1254. X
  1255. X                    /* write the cluster */
  1256. X    sector = (long) (last - 2) * clus_size + dir_start + dir_len;
  1257. X    disk_write(sector, tbuf, buflen);
  1258. X
  1259. X                    /* fix up the globals.... */
  1260. X    num = dir_entries / 16;
  1261. X    dir_entries += clus_size * 16;
  1262. X    for (i = 0; i < clus_size; i++)
  1263. X        dir_chain[num + i] = sector + i;
  1264. X
  1265. X                    /* fix up dir_buf.... */
  1266. X    new = num + clus_size;
  1267. X    dir_buf = (unsigned char *) realloc((char *) dir_buf, (unsigned int) new * MSECTOR_SIZE);
  1268. X    if (dir_buf == NULL) {
  1269. X        perror("dir_grow: malloc");
  1270. X        exit(1);
  1271. X    }
  1272. X    offset = dir_buf + (num * MSECTOR_SIZE);
  1273. X    disk_read(dir_chain[num], offset, clus_size * MSECTOR_SIZE);
  1274. X    return(0);
  1275. X}
  1276. X
  1277. X/*
  1278. X * Returns next free cluster or 1 if none are available.
  1279. X */
  1280. X
  1281. Xunsigned int
  1282. Xnext_fat(last)
  1283. Xunsigned int last;
  1284. X{
  1285. X    register unsigned int i;
  1286. X    unsigned int fat_decode();
  1287. X
  1288. X    for (i = last + 1; i < num_clus + 2; i++) {
  1289. X        if (!fat_decode(i))
  1290. X            return(i);
  1291. X    }
  1292. X    return(1);
  1293. X}
  1294. END_OF_FILE
  1295. if test 2037 -ne `wc -c <'mtools/dir_make.c'`; then
  1296.     echo shar: \"'mtools/dir_make.c'\" unpacked with wrong size!
  1297. fi
  1298. # end of 'mtools/dir_make.c'
  1299. fi
  1300. if test -f 'mtools/expand.c' -a "${1}" != "-c" ; then 
  1301.   echo shar: Will not clobber existing file \"'mtools/expand.c'\"
  1302. else
  1303. echo shar: Extracting \"'mtools/expand.c'\" \(1738 characters\)
  1304. sed "s/^X//" >'mtools/expand.c' <<'END_OF_FILE'
  1305. X/*
  1306. X * Do filename expansion with the shell.  Returns a pointer to a
  1307. X * static area.
  1308. X */
  1309. X
  1310. X#define EXPAND_BUF    2048
  1311. X
  1312. X#include <stdio.h>
  1313. X
  1314. Xchar *
  1315. Xexpand(input)
  1316. Xchar *input;
  1317. X{
  1318. X    FILE *fp, *popen();
  1319. X    int last;
  1320. X    char buf[256], *strpbrk(), *strcpy();
  1321. X    static char ans[EXPAND_BUF];
  1322. X
  1323. X    if (input == NULL)
  1324. X        return(NULL);
  1325. X    if (*input == '\0')
  1326. X        return("");
  1327. X                    /* any thing to expand? */
  1328. X    if (!strpbrk(input, "$*{}[]\\?~")) {
  1329. X        strcpy(ans, input);
  1330. X        return(ans);
  1331. X    }
  1332. X                    /* popen an echo */
  1333. X    sprintf(buf, "echo %s", input);
  1334. X
  1335. X    fp = popen(buf, "r");
  1336. X    fgets(ans, EXPAND_BUF, fp);
  1337. X    pclose(fp);
  1338. X
  1339. X    if (!strlen(ans)) {
  1340. X        strcpy(ans, input);
  1341. X        return(ans);
  1342. X    }
  1343. X
  1344. X    /*
  1345. X     * A horrible kludge...  if the last character is not a line feed,
  1346. X     * then the csh has returned an error message.  Otherwise zap the
  1347. X     * line feed.
  1348. X     */
  1349. X    last = strlen(ans) - 1;
  1350. X    if (ans[last] != '\n') {
  1351. X        strcpy(ans, input);
  1352. X        return(ans);
  1353. X    }
  1354. X    else
  1355. X        ans[last] = '\0';
  1356. X
  1357. X    return(ans);
  1358. X}
  1359. X
  1360. X/*
  1361. X * Miscellaneous routines probably missing from Bezerkely
  1362. X */
  1363. X
  1364. X#ifdef BSD
  1365. X/*
  1366. X * Return ptr to first occurrence of any character from `brkset'
  1367. X * in the character string `string'; NULL if none exists.
  1368. X */
  1369. X
  1370. Xchar *
  1371. Xstrpbrk(string, brkset)
  1372. Xregister char *string, *brkset;
  1373. X{
  1374. X    register char *p;
  1375. X
  1376. X    if (!string || !brkset)
  1377. X        return(0);
  1378. X    do {
  1379. X        for (p = brkset; *p != '\0' && *p != *string; ++p)
  1380. X            ;
  1381. X        if (*p != '\0')
  1382. X            return(string);
  1383. X    }
  1384. X    while (*string++);
  1385. X    return(0);
  1386. X}
  1387. X
  1388. X/*
  1389. X * Copies the character c, n times to string s
  1390. X */
  1391. X
  1392. Xchar *
  1393. Xmemset(s, c, n)
  1394. Xchar *s, c;
  1395. Xint n;
  1396. X{
  1397. X    char *s1 = s;
  1398. X
  1399. X    while (n > 0) {
  1400. X        --n;
  1401. X        *s++ = c;
  1402. X    }
  1403. X    return(s1);
  1404. X}
  1405. X
  1406. X/*
  1407. X * Copy contents of memory (with possible overlapping).
  1408. X */
  1409. X
  1410. Xchar *
  1411. Xmemcpy(s1, s2, n)
  1412. Xchar *s1, *s2;
  1413. Xint n;
  1414. X{
  1415. X    bcopy(s2, s1, n);
  1416. X    return(s1);
  1417. X}
  1418. X#endif /* BSD */
  1419. END_OF_FILE
  1420. if test 1738 -ne `wc -c <'mtools/expand.c'`; then
  1421.     echo shar: \"'mtools/expand.c'\" unpacked with wrong size!
  1422. fi
  1423. # end of 'mtools/expand.c'
  1424. fi
  1425. if test -f 'mtools/fat_free.c' -a "${1}" != "-c" ; then 
  1426.   echo shar: Will not clobber existing file \"'mtools/fat_free.c'\"
  1427. else
  1428. echo shar: Extracting \"'mtools/fat_free.c'\" \(728 characters\)
  1429. sed "s/^X//" >'mtools/fat_free.c' <<'END_OF_FILE'
  1430. X#include <stdio.h>
  1431. X#include "msdos.h"
  1432. X
  1433. Xextern int fat_error;
  1434. Xextern unsigned int last_fat;
  1435. X
  1436. X/*
  1437. X * Remove a string of FAT entries (delete the file).  The argument is
  1438. X * the beginning of the string.  Does not consider the file length, so
  1439. X * if FAT is corrupted, watch out!
  1440. X */
  1441. X
  1442. Xint
  1443. Xfat_free(fat)
  1444. Xunsigned int fat;
  1445. X{
  1446. X    unsigned int next, fat_decode();
  1447. X                    /* a zero length file? */
  1448. X    if (fat == 0)
  1449. X        return(0);
  1450. X
  1451. X    /* CONSTCOND */
  1452. X    while (1) {
  1453. X                    /* get next cluster number */
  1454. X        next = fat_decode(fat);
  1455. X                    /* mark current cluster as empty */
  1456. X        if (fat_encode(fat, 0) || next == 1) {
  1457. X            fprintf(stderr, "fat_free: FAT problem\n");
  1458. X            fat_error++;
  1459. X            return(-1);
  1460. X        }
  1461. X        if (next >= last_fat)
  1462. X            break;
  1463. X        fat = next;
  1464. X    }
  1465. X    return(0);
  1466. X}
  1467. END_OF_FILE
  1468. if test 728 -ne `wc -c <'mtools/fat_free.c'`; then
  1469.     echo shar: \"'mtools/fat_free.c'\" unpacked with wrong size!
  1470. fi
  1471. # end of 'mtools/fat_free.c'
  1472. fi
  1473. if test -f 'mtools/fat_read.c' -a "${1}" != "-c" ; then 
  1474.   echo shar: Will not clobber existing file \"'mtools/fat_read.c'\"
  1475. else
  1476. echo shar: Extracting \"'mtools/fat_read.c'\" \(2500 characters\)
  1477. sed "s/^X//" >'mtools/fat_read.c' <<'END_OF_FILE'
  1478. X#include <stdio.h>
  1479. X#include "msdos.h"
  1480. X
  1481. Xint fat_len;                /* length of FAT table (in sectors) */
  1482. Xunsigned int end_fat;            /* the end-of-chain marker */
  1483. Xunsigned int last_fat;            /* the last in a chain marker */
  1484. Xunsigned char *fat_buf;            /* the File Allocation Table */
  1485. X
  1486. Xextern int fat_bits;
  1487. X
  1488. X/*
  1489. X * Get and decode a FAT (file allocation table) entry.  Returns the cluster
  1490. X * number on success or 1 on failure.
  1491. X */
  1492. X
  1493. Xunsigned int
  1494. Xfat_decode(num)
  1495. Xunsigned int num;
  1496. X{
  1497. X    unsigned int fat, fat_hi, fat_low, byte_1, byte_2;
  1498. X    int start;
  1499. X
  1500. X    if (fat_bits == 12) {
  1501. X        /*
  1502. X         *    |    byte n     |   byte n+1    |   byte n+2    |
  1503. X         *    |7|6|5|4|3|2|1|0|7|6|5|4|3|2|1|0|7|6|5|4|3|2|1|0|
  1504. X         *    | | | | | | | | | | | | | | | | | | | | | | | | |
  1505. X         *    | n+0.0 | n+0.5 | n+1.0 | n+1.5 | n+2.0 | n+2.5 |
  1506. X         *        \_____  \____   \______/________/_____   /
  1507. X         *          ____\______\________/   _____/  ____\_/
  1508. X         *         /     \      \          /       /     \
  1509. X         *    | n+1.5 | n+0.0 | n+0.5 | n+2.0 | n+2.5 | n+1.0 |
  1510. X         *    |      FAT entry k      |    FAT entry k+1      |
  1511. X         */
  1512. X                    /* which bytes contain the entry */
  1513. X        start = num * 3 / 2;
  1514. X        if (start <= 2 || start + 1 > (fat_len * MSECTOR_SIZE))
  1515. X            return(1);
  1516. X
  1517. X        byte_1 = *(fat_buf + start);
  1518. X        byte_2 = *(fat_buf + start + 1);
  1519. X                    /* (odd) not on byte boundary */
  1520. X        if (num % 2) {
  1521. X            fat_hi = (byte_2 & 0xff) << 4;
  1522. X            fat_low = (byte_1 & 0xf0) >> 4;
  1523. X        }
  1524. X                    /* (even) on byte boundary */
  1525. X        else {
  1526. X            fat_hi = (byte_2 & 0xf) << 8;
  1527. X            fat_low = byte_1 & 0xff;
  1528. X        }
  1529. X        fat = (fat_hi + fat_low) & 0xfff;
  1530. X    }
  1531. X    else {
  1532. X        /*
  1533. X         *    |    byte n     |   byte n+1    |
  1534. X         *    |7|6|5|4|3|2|1|0|7|6|5|4|3|2|1|0|
  1535. X         *    | | | | | | | | | | | | | | | | |
  1536. X         *    |         FAT entry k           |
  1537. X         */
  1538. X                    /* which bytes contain the entry */
  1539. X        start = num * 2;
  1540. X        if (start <= 3 || start + 1 > (fat_len * MSECTOR_SIZE))
  1541. X            return(1);
  1542. X
  1543. X        fat = (*(fat_buf + start + 1) * 0x100) + *(fat_buf + start);
  1544. X    }
  1545. X    return(fat);
  1546. X}
  1547. X
  1548. X/*
  1549. X * Read the entire FAT table into memory.
  1550. X */
  1551. X
  1552. Xvoid
  1553. Xfat_read(start)
  1554. Xint start;
  1555. X{
  1556. X    int buflen;
  1557. X    char *malloc();
  1558. X    void perror(), exit(), disk_read();
  1559. X                    /* only the first copy of the FAT */
  1560. X    buflen = fat_len * MSECTOR_SIZE;
  1561. X    fat_buf = (unsigned char *) malloc((unsigned int) buflen);
  1562. X    if (fat_buf == NULL) {
  1563. X        perror("fat_read: malloc");
  1564. X        exit(1);
  1565. X    }
  1566. X                    /* read the FAT sectors */
  1567. X    disk_read((long) start, fat_buf, buflen);
  1568. X
  1569. X                    /* the encoding scheme */
  1570. X    if (fat_bits == 12) {
  1571. X        end_fat = 0xfff;
  1572. X        last_fat = 0xff8;
  1573. X    }
  1574. X    else {
  1575. X        end_fat = 0xffff;
  1576. X        last_fat = 0xfff8;
  1577. X    }
  1578. X    return;
  1579. X}
  1580. END_OF_FILE
  1581. if test 2500 -ne `wc -c <'mtools/fat_read.c'`; then
  1582.     echo shar: \"'mtools/fat_read.c'\" unpacked with wrong size!
  1583. fi
  1584. # end of 'mtools/fat_read.c'
  1585. fi
  1586. if test -f 'mtools/fat_write.c' -a "${1}" != "-c" ; then 
  1587.   echo shar: Will not clobber existing file \"'mtools/fat_write.c'\"
  1588. else
  1589. echo shar: Extracting \"'mtools/fat_write.c'\" \(2442 characters\)
  1590. sed "s/^X//" >'mtools/fat_write.c' <<'END_OF_FILE'
  1591. X#include <stdio.h>
  1592. X#include "msdos.h"
  1593. X
  1594. Xextern int fd, dir_start, num_fat, fat_len, fat_error, fat_bits;
  1595. Xextern unsigned char *fat_buf;
  1596. X
  1597. X/*
  1598. X * Puts a code into the FAT table.  Is the opposite of fat_decode().  No
  1599. X * sanity checking is done on the code.  Returns a 1 on error.
  1600. X */
  1601. X
  1602. Xint
  1603. Xfat_encode(num, code)
  1604. Xunsigned int num;
  1605. Xunsigned int code;
  1606. X{
  1607. X    int start;
  1608. X
  1609. X    if (fat_bits == 12) {
  1610. X        /*
  1611. X         *    |    byte n     |   byte n+1    |   byte n+2    |
  1612. X         *    |7|6|5|4|3|2|1|0|7|6|5|4|3|2|1|0|7|6|5|4|3|2|1|0|
  1613. X         *    | | | | | | | | | | | | | | | | | | | | | | | | |
  1614. X         *    | n+0.0 | n+0.5 | n+1.0 | n+1.5 | n+2.0 | n+2.5 |
  1615. X         *        \_____  \____   \______/________/_____   /
  1616. X         *          ____\______\________/   _____/  ____\_/
  1617. X         *         /     \      \          /       /     \
  1618. X         *    | n+1.5 | n+0.0 | n+0.5 | n+2.0 | n+2.5 | n+1.0 |
  1619. X         *    |      FAT entry k      |    FAT entry k+1      |
  1620. X         */
  1621. X                    /* which bytes contain the entry */
  1622. X        start = num * 3 / 2;
  1623. X        if (start <= 2 || start + 1 > (fat_len * MSECTOR_SIZE))
  1624. X            return(1);
  1625. X                    /* (odd) not on byte boundary */
  1626. X        if (num % 2) {
  1627. X            *(fat_buf + start) = (*(fat_buf + start) & 0x0f) + ((code << 4) & 0xf0);
  1628. X            *(fat_buf + start + 1) = (code >> 4) & 0xff;
  1629. X        }
  1630. X                    /* (even) on byte boundary */
  1631. X        else {
  1632. X            *(fat_buf + start) = code & 0xff;
  1633. X            *(fat_buf + start + 1) = (*(fat_buf + start + 1) & 0xf0) + ((code >> 8) & 0x0f);
  1634. X        }
  1635. X    }
  1636. X    else {
  1637. X        /*
  1638. X         *    |    byte n     |   byte n+1    |
  1639. X         *    |7|6|5|4|3|2|1|0|7|6|5|4|3|2|1|0|
  1640. X         *    | | | | | | | | | | | | | | | | |
  1641. X         *    |         FAT entry k           |
  1642. X         */
  1643. X                    /* which bytes contain the entry */
  1644. X        start = num * 2;
  1645. X        if (start <= 3 || start + 1 > (fat_len * MSECTOR_SIZE))
  1646. X            return(1);
  1647. X
  1648. X        *(fat_buf + start + 1) =  code / 0x100;
  1649. X        *(fat_buf + start) =  code % 0x100;
  1650. X    }
  1651. X    return(0);
  1652. X}
  1653. X
  1654. X/*
  1655. X * Write the FAT table to the disk.  Up to now the FAT manipulation has
  1656. X * been done in memory.  All errors are fatal.  (Might not be too smart
  1657. X * to wait till the end of the program to write the table.  Oh well...)
  1658. X */
  1659. X
  1660. Xvoid
  1661. Xfat_write()
  1662. X{
  1663. X    int fat_start, buflen, dups;
  1664. X    void disk_write();
  1665. X
  1666. X    if (fd < 0)
  1667. X        return;
  1668. X
  1669. X    fat_start = dir_start - (fat_len * num_fat);
  1670. X    buflen = fat_len * MSECTOR_SIZE;
  1671. X
  1672. X    disk_write((long) fat_start, fat_buf, buflen);
  1673. X
  1674. X    /*
  1675. X     * Only duplicate the FAT table if no errors were detected
  1676. X     */
  1677. X    if (!fat_error) {
  1678. X        dups = num_fat - 1;
  1679. X        while (dups--) {
  1680. X            fat_start += fat_len;
  1681. X            disk_write((long) fat_start, fat_buf, buflen);
  1682. X        }
  1683. X    }
  1684. X    return;
  1685. X}
  1686. END_OF_FILE
  1687. if test 2442 -ne `wc -c <'mtools/fat_write.c'`; then
  1688.     echo shar: \"'mtools/fat_write.c'\" unpacked with wrong size!
  1689. fi
  1690. # end of 'mtools/fat_write.c'
  1691. fi
  1692. if test -f 'mtools/file_read.c' -a "${1}" != "-c" ; then 
  1693.   echo shar: Will not clobber existing file \"'mtools/file_read.c'\"
  1694. else
  1695. echo shar: Extracting \"'mtools/file_read.c'\" \(1825 characters\)
  1696. sed "s/^X//" >'mtools/file_read.c' <<'END_OF_FILE'
  1697. X#include <stdio.h>
  1698. X#include "msdos.h"
  1699. X
  1700. Xextern int clus_size, dir_start, dir_len, fat_error;
  1701. Xextern unsigned int last_fat;
  1702. X
  1703. X/*
  1704. X * Read the clusters given the beginning FAT entry.  Returns 0 on success.
  1705. X */
  1706. X
  1707. Xint
  1708. Xfile_read(fp, fat, textmode, stripmode, size)
  1709. XFILE *fp;
  1710. Xunsigned int fat;
  1711. Xint textmode, stripmode;
  1712. Xlong size;
  1713. X{
  1714. X    register int i;
  1715. X    int in_len, out_len;
  1716. X    unsigned int fat_decode();
  1717. X    long current, start;
  1718. X    unsigned char in_buf[MAX_CLUSTER], out_buf[MAX_CLUSTER];
  1719. X    void disk_read(), perror();
  1720. X
  1721. X    current = 0L;
  1722. X    in_len = clus_size * MSECTOR_SIZE;
  1723. X                    /* a zero length file? */
  1724. X    if (fat == 0)
  1725. X        return(0);
  1726. X
  1727. X    /* CONSTCOND */
  1728. X    while (1) {
  1729. X        start = (long) (fat - 2) * clus_size + dir_start + dir_len;
  1730. X        disk_read(start, in_buf, in_len);
  1731. X
  1732. X                    /* do the translations */
  1733. X        if (textmode || stripmode) {
  1734. X            out_len = 0;
  1735. X            for (i = 0; i < in_len; i++) {
  1736. X                current++;
  1737. X                if (current > size)
  1738. X                    break;
  1739. X                if (textmode && in_buf[i] == '\r')
  1740. X                    continue;
  1741. X                if (textmode && current == size && in_buf[i] == 0x1a)
  1742. X                    continue;
  1743. X                if (stripmode)
  1744. X                    out_buf[out_len++] = in_buf[i] & 0x7f;
  1745. X                else
  1746. X                    out_buf[out_len++] = in_buf[i];
  1747. X            }
  1748. X                    /* write it */
  1749. X            if (fwrite((char *) out_buf, sizeof(*out_buf), out_len, fp) == 0) {
  1750. X                perror("file_write: fwrite");
  1751. X                return(-1);
  1752. X            }
  1753. X        }
  1754. X                    /* much easier... */
  1755. X        else {
  1756. X            out_len = (size - current > in_len) ? in_len : size - current;
  1757. X            if (fwrite((char *) in_buf, sizeof(*in_buf), out_len, fp) == 0) {
  1758. X                perror("file_write: fwrite");
  1759. X                return(-1);
  1760. X            }
  1761. X
  1762. X            current += out_len;
  1763. X            if (current >= size)
  1764. X                break;
  1765. X        }
  1766. X
  1767. X                    /* get next cluster number */
  1768. X        fat = fat_decode(fat);
  1769. X        if (fat == 1) {
  1770. X            fprintf(stderr, "file_read: FAT problem\n");
  1771. X            fat_error++;
  1772. X            return(-1);
  1773. X        }
  1774. X                    /* end of cluster chain */
  1775. X        if (fat >= last_fat)
  1776. X            break;
  1777. X    }
  1778. X    return(0);
  1779. X}
  1780. END_OF_FILE
  1781. if test 1825 -ne `wc -c <'mtools/file_read.c'`; then
  1782.     echo shar: \"'mtools/file_read.c'\" unpacked with wrong size!
  1783. fi
  1784. # end of 'mtools/file_read.c'
  1785. fi
  1786. if test -f 'mtools/file_write.c' -a "${1}" != "-c" ; then 
  1787.   echo shar: Will not clobber existing file \"'mtools/file_write.c'\"
  1788. else
  1789. echo shar: Extracting \"'mtools/file_write.c'\" \(2342 characters\)
  1790. sed "s/^X//" >'mtools/file_write.c' <<'END_OF_FILE'
  1791. X#include <stdio.h>
  1792. X#include "msdos.h"
  1793. X
  1794. Xextern int full, fat_error, clus_size, dir_start, dir_len;
  1795. Xextern unsigned end_fat;
  1796. X
  1797. Xstatic int need_nl, put_cluster();
  1798. X
  1799. X/*
  1800. X * Write out clusters with input from the given file pointer.   Returns the
  1801. X * size of the file (which may have changed) or -1 on error.
  1802. X */
  1803. X
  1804. Xlong
  1805. Xfile_write(fp, firstfat, filesize, textmode)
  1806. XFILE *fp;
  1807. Xunsigned int firstfat;
  1808. Xlong filesize;
  1809. Xint textmode;
  1810. X{
  1811. X    int i;
  1812. X    unsigned int fat, oldfat, next_fat();
  1813. X    long size;
  1814. X
  1815. X    oldfat = 0;
  1816. X    fat = firstfat;
  1817. X    need_nl = 0;
  1818. X    size = 0L;
  1819. X
  1820. X    /* CONSTCOND */
  1821. X    while (1) {
  1822. X        if ((i = put_cluster(fp, fat, &filesize, textmode)) < 0) {
  1823. X            if (oldfat) {
  1824. X                fat_encode(oldfat, end_fat);
  1825. X                if (fat_free(firstfat))
  1826. X                    fat_error++;
  1827. X                full = 1;
  1828. X            }
  1829. X            return(-1);
  1830. X        }
  1831. X
  1832. X        size += i;
  1833. X        if (size >= filesize) {
  1834. X            fat_encode(fat, end_fat);
  1835. X            break;
  1836. X        }
  1837. X        oldfat = fat;
  1838. X                    /* get next free cluster */
  1839. X        fat = next_fat(oldfat);
  1840. X        if (fat == 1) {
  1841. X            fat_encode(oldfat, end_fat);
  1842. X                    /* delete it, if doesn't fit */
  1843. X            if (fat_free(firstfat))
  1844. X                fat_error++;
  1845. X            full = 1;
  1846. X            return(-1);
  1847. X        }
  1848. X        fat_encode(oldfat, fat);
  1849. X    }
  1850. X    return(size);
  1851. X}
  1852. X
  1853. X/*
  1854. X * Write to the cluster from the named Unix file descriptor.  Returns the
  1855. X * size of what was written, or -1 on error.
  1856. X */
  1857. X
  1858. Xstatic int
  1859. Xput_cluster(fp, num, filesize, textmode)
  1860. XFILE *fp;
  1861. Xunsigned int num;
  1862. Xlong *filesize;
  1863. Xint textmode;
  1864. X{
  1865. X    int i, buflen, c;
  1866. X    long start;
  1867. X    unsigned char tbuf[MAX_CLUSTER];
  1868. X    void disk_write(), perror();
  1869. X
  1870. X    start = (long) (num - 2) * clus_size + dir_start + dir_len;
  1871. X    buflen = clus_size * MSECTOR_SIZE;
  1872. X                    /* '\n' to '\r\n' translation */
  1873. X    if (textmode) {
  1874. X        i = 0;
  1875. X        if (need_nl) {
  1876. X            tbuf[i++] = '\n';
  1877. X            need_nl = 0;
  1878. X        }
  1879. X        while (i < buflen) {
  1880. X            if ((c = fgetc(fp)) == EOF) {
  1881. X                    /* put a file EOF marker */
  1882. X                tbuf[i++] = 0x1a;
  1883. X                    /* make the file appear larger */
  1884. X                *filesize = *filesize + 1;
  1885. X                break;
  1886. X            }
  1887. X            if (c == '\n') {
  1888. X                tbuf[i++] = '\r';
  1889. X                    /* make the file appear larger */
  1890. X                *filesize = *filesize + 1;
  1891. X                    /* if at the end of the buffer */
  1892. X                if (i == buflen) {
  1893. X                    need_nl++;
  1894. X                    break;
  1895. X                }
  1896. X            }
  1897. X            tbuf[i++] = (unsigned char) c;
  1898. X        }
  1899. X    }
  1900. X                    /* much easier.... */
  1901. X    else {
  1902. X        if ((i = fread((char *) tbuf, sizeof(*tbuf), buflen, fp)) <= 0) {
  1903. X            perror("putcluster: fread");
  1904. X            return(-1);
  1905. X        }
  1906. X    }
  1907. X
  1908. X    disk_write(start, tbuf, buflen);
  1909. X    return(i);
  1910. X}
  1911. END_OF_FILE
  1912. if test 2342 -ne `wc -c <'mtools/file_write.c'`; then
  1913.     echo shar: \"'mtools/file_write.c'\" unpacked with wrong size!
  1914. fi
  1915. # end of 'mtools/file_write.c'
  1916. fi
  1917. if test -f 'mtools/is_dir.c' -a "${1}" != "-c" ; then 
  1918.   echo shar: Will not clobber existing file \"'mtools/is_dir.c'\"
  1919. else
  1920. echo shar: Extracting \"'mtools/is_dir.c'\" \(907 characters\)
  1921. sed "s/^X//" >'mtools/is_dir.c' <<'END_OF_FILE'
  1922. X/*
  1923. X * Test to see if a filename is a directory.  Subdir() has to be called
  1924. X * on the directory above this one first...  Returns 1 if true.
  1925. X */
  1926. X
  1927. X#include <stdio.h>
  1928. X#include "msdos.h"
  1929. X
  1930. Xextern int dir_entries;
  1931. X
  1932. Xint
  1933. Xis_dir(path)
  1934. Xchar *path;
  1935. X{
  1936. X    register int entry;
  1937. X    char *newname, *unix_name();
  1938. X    struct directory *dir, *dir_read();
  1939. X                    /* no path */
  1940. X    if (*path == '\0')
  1941. X        return(0);
  1942. X
  1943. X    for (entry = 0; entry < dir_entries; entry++) {
  1944. X        dir = dir_read(entry);
  1945. X                    /* if empty */
  1946. X        if (dir->name[0] == 0x0)
  1947. X            break;
  1948. X                    /* if erased */
  1949. X        if (dir->name[0] == 0xe5)
  1950. X            continue;
  1951. X                    /* skip if not a directory */
  1952. X        if (!(dir->attr & 0x10))
  1953. X            continue;
  1954. X
  1955. X        newname = unix_name(dir->name, dir->ext);
  1956. X        if (match(newname, path))
  1957. X            return(1);
  1958. X    }
  1959. X
  1960. X    /*
  1961. X     * If the file is "." or ".." but it fails to match, then you
  1962. X     * must be at root
  1963. X     */
  1964. X    if (!strcmp(path, ".") || !strcmp(path, ".."))
  1965. X        return(1);
  1966. X
  1967. X    return(0);
  1968. X}
  1969. END_OF_FILE
  1970. if test 907 -ne `wc -c <'mtools/is_dir.c'`; then
  1971.     echo shar: \"'mtools/is_dir.c'\" unpacked with wrong size!
  1972. fi
  1973. # end of 'mtools/is_dir.c'
  1974. fi
  1975. if test -f 'mtools/match.c' -a "${1}" != "-c" ; then 
  1976.   echo shar: Will not clobber existing file \"'mtools/match.c'\"
  1977. else
  1978. echo shar: Extracting \"'mtools/match.c'\" \(1657 characters\)
  1979. sed "s/^X//" >'mtools/match.c' <<'END_OF_FILE'
  1980. X/*
  1981. X * Do shell-style pattern matching for '?', '\', '[..]', and '*' wildcards.
  1982. X * Returns 1 if match, 0 if not.
  1983. X */
  1984. X
  1985. X#include <stdio.h>
  1986. X
  1987. Xint
  1988. Xmatch(s, p)
  1989. Xchar *s, *p;
  1990. X{
  1991. X    int matched, reverse;
  1992. X    char first, last;
  1993. X
  1994. X    for (; *p != '\0'; s++, p++) {
  1995. X        switch (*p) {
  1996. X            case '?':    /* match any one character */
  1997. X                if (*s == '\0')
  1998. X                    return(0);
  1999. X                break;
  2000. X            case '*':    /* match everything */
  2001. X                while (*p == '*')
  2002. X                    p++;
  2003. X
  2004. X                    /* if last char in pattern */
  2005. X                if (*p == '\0')
  2006. X                    return(1);
  2007. X
  2008. X                    /* search for next char in pattern */
  2009. X                matched = 0;
  2010. X                while (*s != '\0') {
  2011. X                    if (*s == *p) {
  2012. X                        matched = 1;
  2013. X                        break;
  2014. X                    }
  2015. X                    s++;
  2016. X                }
  2017. X                if (!matched)
  2018. X                    return(0);
  2019. X                break;
  2020. X            case '[':     /* match range of characters */
  2021. X                first = '\0';
  2022. X                matched = 0;
  2023. X                reverse = 0;
  2024. X                while (*++p != ']') {
  2025. X                    if (*p == '^') {
  2026. X                        reverse = 1;
  2027. X                        p++;
  2028. X                    }
  2029. X                    first = *p;
  2030. X                    if (first == ']' || first == '\0')
  2031. X                        return(0);
  2032. X
  2033. X                    /* if 2nd char is '-' */
  2034. X                    if (*(p + 1) == '-') {
  2035. X                        p++;
  2036. X                    /* set last to 3rd char ... */
  2037. X                        last = *++p;
  2038. X                        if (last == ']' || last == '\0')
  2039. X                            return(0);
  2040. X                    /* test the range of values */
  2041. X                        if (*s >= first && *s <= last) {
  2042. X                            matched = 1;
  2043. X                            p++;
  2044. X                            break;
  2045. X                        }
  2046. X                        return(0);
  2047. X                    }
  2048. X                    if (*s == *p)
  2049. X                        matched = 1;
  2050. X                }
  2051. X                if (matched && reverse)
  2052. X                    return(0);
  2053. X                if (!matched)
  2054. X                    return(0);
  2055. X                break;
  2056. X            case '\\':    /* Literal match with next character */
  2057. X                p++;
  2058. X                /* fall thru */
  2059. X            default:
  2060. X                if (*s != *p)
  2061. X                    return(0);
  2062. X                break;
  2063. X        }
  2064. X    }
  2065. X                    /* string ended prematurely ? */
  2066. X    if (*s != '\0')
  2067. X        return(0);
  2068. X    else
  2069. X        return(1);
  2070. X}
  2071. END_OF_FILE
  2072. if test 1657 -ne `wc -c <'mtools/match.c'`; then
  2073.     echo shar: \"'mtools/match.c'\" unpacked with wrong size!
  2074. fi
  2075. # end of 'mtools/match.c'
  2076. fi
  2077. if test -f 'mtools/mkmanifest.c' -a "${1}" != "-c" ; then 
  2078.   echo shar: Will not clobber existing file \"'mtools/mkmanifest.c'\"
  2079. else
  2080. echo shar: Extracting \"'mtools/mkmanifest.c'\" \(2306 characters\)
  2081. sed "s/^X//" >'mtools/mkmanifest.c' <<'END_OF_FILE'
  2082. X/*
  2083. X * A program to create a manifest (shiping list) that is a shell script
  2084. X * to return a Unix file name to it's original state after it has been
  2085. X * clobbered by MSDOS's file name restrictions.
  2086. X *
  2087. X *    This code also used in arc, mtools, and pcomm
  2088. X */
  2089. X
  2090. X#ifdef BSD
  2091. X#define strrchr rindex
  2092. X#endif /* BSD */
  2093. X
  2094. X#include <stdio.h>
  2095. X#include <ctype.h>
  2096. X
  2097. Xmain(argc, argv)
  2098. Xint argc;
  2099. Xchar *argv[];
  2100. X{
  2101. X    int i;
  2102. X    char *name, *new_name, *dos_name(), *strrchr();
  2103. X    void exit();
  2104. X
  2105. X    if (argc == 1) {
  2106. X        fprintf(stderr, "Usage: mkmanifest <list-of-files>\n");
  2107. X        exit(1);
  2108. X    }
  2109. X
  2110. X    for (i=1; i<argc; i++) {
  2111. X                    /* zap the leading path */
  2112. X        if (name = strrchr(argv[i], '/'))
  2113. X            name++;
  2114. X        else
  2115. X            name = argv[i];
  2116. X                    /* create new name */
  2117. X        new_name = dos_name(name);
  2118. X
  2119. X        if (strcmp(new_name, name))
  2120. X            printf("mv %s %s\n", new_name, name);
  2121. X    }
  2122. X    exit(0);
  2123. X}
  2124. X
  2125. Xchar *
  2126. Xdos_name(name)
  2127. Xchar *name;
  2128. X{
  2129. X    static char *dev[9] = {"con", "aux", "com1", "com2", "lpt1", "prn",
  2130. X    "lpt2", "lpt3", "nul"};
  2131. X    char *s, *temp, *ext, *strcpy(), *strpbrk(), *strcat();
  2132. X    char buf[15];
  2133. X    int i, dot;
  2134. X    static char ans[13];
  2135. X
  2136. X    strcpy(buf, name);
  2137. X    temp = buf;
  2138. X                    /* separate the name from extention */
  2139. X    ext = "";
  2140. X    dot = 0;
  2141. X    for (i=strlen(buf)-1; i>=0; i--) {
  2142. X        if (buf[i] == '.' && !dot) {
  2143. X            dot = 1;
  2144. X            buf[i] = '\0';
  2145. X            ext = &buf[i+1];
  2146. X        }
  2147. X        if (isupper(buf[i]))
  2148. X            buf[i] = tolower(buf[i]);
  2149. X    }
  2150. X                    /* if no name */
  2151. X    if (*temp == '\0')
  2152. X        temp = "x";
  2153. X                    /* if name is a device */
  2154. X    for (i=0; i<9; i++) {
  2155. X        if (!strcmp(temp, dev[i])) 
  2156. X            *temp = 'x';
  2157. X    }
  2158. X                    /* name too long? */
  2159. X    if (strlen(temp) > 8)
  2160. X        *(temp+8) = '\0';
  2161. X                    /* extention too long? */
  2162. X    if (strlen(ext) > 3)
  2163. X        *(ext+3) = '\0';
  2164. X                    /* illegal characters? */
  2165. X    while (s = strpbrk(temp, "^+=/[]:',?*\\<>|\". "))
  2166. X        *s = 'x';
  2167. X
  2168. X    while (s = strpbrk(ext, "^+=/[]:',?*\\<>|\". "))
  2169. X        *s = 'x';
  2170. X
  2171. X    strcpy(ans, temp);
  2172. X    if (*ext) {
  2173. X        strcat(ans, ".");
  2174. X        strcat(ans, ext);
  2175. X    }
  2176. X    return(ans);
  2177. X}
  2178. X
  2179. X#ifdef BSD
  2180. X/*
  2181. X * Return ptr to first occurrence of any character from `brkset'
  2182. X * in the character string `string'; NULL if none exists.
  2183. X */
  2184. X
  2185. Xchar *
  2186. Xstrpbrk(string, brkset)
  2187. Xregister char *string, *brkset;
  2188. X{
  2189. X    register char *p;
  2190. X
  2191. X    if (!string || !brkset)
  2192. X        return(0);
  2193. X    do {
  2194. X        for (p = brkset; *p != '\0' && *p != *string; ++p)
  2195. X            ;
  2196. X        if (*p != '\0')
  2197. X            return(string);
  2198. X    }
  2199. X    while (*string++);
  2200. X    return(0);
  2201. X}
  2202. X#endif /* BSD */
  2203. END_OF_FILE
  2204. if test 2306 -ne `wc -c <'mtools/mkmanifest.c'`; then
  2205.     echo shar: \"'mtools/mkmanifest.c'\" unpacked with wrong size!
  2206. fi
  2207. # end of 'mtools/mkmanifest.c'
  2208. fi
  2209. if test -f 'mtools/msdos.h' -a "${1}" != "-c" ; then 
  2210.   echo shar: Will not clobber existing file \"'mtools/msdos.h'\"
  2211. else
  2212. echo shar: Extracting \"'mtools/msdos.h'\" \(2049 characters\)
  2213. sed "s/^X//" >'mtools/msdos.h' <<'END_OF_FILE'
  2214. X/*
  2215. X * msdos common header file
  2216. X */
  2217. X
  2218. X#define MSECTOR_SIZE    512        /* MSDOS sector size in bytes */
  2219. X#define MDIR_SIZE    32        /* MSDOS directory size in bytes */
  2220. X#define MAX_CLUSTER    8192        /* largest cluster size */
  2221. X#define MAX_PATH    128        /* largest MSDOS path length */
  2222. X#define MAX_DIR_SECS    64        /* largest directory (in sectors) */
  2223. X
  2224. X#define NEW        1
  2225. X#define OLD        0
  2226. X
  2227. Xstruct directory {
  2228. X    unsigned char name[8];        /* file name */
  2229. X    unsigned char ext[3];        /* file extension */
  2230. X    unsigned char attr;        /* attribute byte */
  2231. X    unsigned char reserved[10];    /* ?? */
  2232. X    unsigned char time[2];        /* time stamp */
  2233. X    unsigned char date[2];        /* date stamp */
  2234. X    unsigned char start[2];        /* starting cluster number */
  2235. X    unsigned char size[4];        /* size of the file */
  2236. X};
  2237. X
  2238. Xstruct device {
  2239. X    char drive;            /* the drive letter */
  2240. X    char *name;            /* full path to device */
  2241. X    long offset;            /* skip this many bytes */
  2242. X    int fat_bits;            /* FAT encoding scheme */
  2243. X    int mode;            /* any special open() flags */
  2244. X    int (*gioctl) ();        /* gioctl() function if needed */
  2245. X    int tracks;            /* tracks */
  2246. X    int heads;            /* heads */
  2247. X    int sectors;            /* sectors */
  2248. X};
  2249. X
  2250. Xstruct bootsector {
  2251. X    unsigned char jump[3];        /* Jump to boot code */
  2252. X    unsigned char banner[8];    /* OEM name & version */
  2253. X    unsigned char secsiz[2];    /* Bytes per sector hopefully 512 */
  2254. X    unsigned char clsiz;        /* Cluster size in sectors */
  2255. X    unsigned char nrsvsect[2];    /* Number of reserved (boot) sectors */
  2256. X    unsigned char nfat;        /* Number of FAT tables hopefully 2 */
  2257. X    unsigned char dirents[2];    /* Number of directory slots */
  2258. X    unsigned char psect[2];        /* Total sectors on disk */
  2259. X    unsigned char descr;        /* Media descriptor=first byte of FAT */
  2260. X    unsigned char fatlen[2];    /* Sectors in FAT */
  2261. X    unsigned char nsect[2];        /* Sectors/track */
  2262. X    unsigned char nheads[2];    /* Heads */
  2263. X    unsigned char nhs[4];        /* number of hidden sectors */
  2264. X    unsigned char bigsect[4];    /* big total sectors */
  2265. X    unsigned char junk[476];    /* who cares? */
  2266. X};
  2267. X
  2268. Xtypedef void SIG_TYPE;
  2269. X/* typedef int SIG_TYPE; */
  2270. X
  2271. X#ifdef BSD
  2272. X#define strchr index
  2273. X#define strrchr rindex
  2274. X#endif /* BSD */
  2275. END_OF_FILE
  2276. if test 2049 -ne `wc -c <'mtools/msdos.h'`; then
  2277.     echo shar: \"'mtools/msdos.h'\" unpacked with wrong size!
  2278. fi
  2279. # end of 'mtools/msdos.h'
  2280. fi
  2281. if test -f 'mtools/parse.c' -a "${1}" != "-c" ; then 
  2282.   echo shar: Will not clobber existing file \"'mtools/parse.c'\"
  2283. else
  2284. echo shar: Extracting \"'mtools/parse.c'\" \(2194 characters\)
  2285. sed "s/^X//" >'mtools/parse.c' <<'END_OF_FILE'
  2286. X#include <stdio.h>
  2287. X#include <ctype.h>
  2288. X#include "msdos.h"
  2289. X
  2290. Xextern char *mcwd;
  2291. X
  2292. X/*
  2293. X * Get name component of filename.  Translates name to upper case.  Returns
  2294. X * pointer to static area.
  2295. X */
  2296. X
  2297. Xchar *
  2298. Xget_name(filename)
  2299. Xchar *filename;
  2300. X{
  2301. X    char *s, *temp, *strcpy(), *strrchr(), buf[MAX_PATH];
  2302. X    static char ans[13];
  2303. X
  2304. X    strcpy(buf, filename);
  2305. X    temp = buf;
  2306. X                    /* skip drive letter */
  2307. X    if (buf[0] && buf[1] == ':')
  2308. X        temp = &buf[2];
  2309. X                    /* find the last separator */
  2310. X    if (s = strrchr(temp, '/'))
  2311. X        temp = s + 1;
  2312. X    if (s = strrchr(temp, '\\'))
  2313. X        temp = s + 1;
  2314. X                    /* xlate to upper case */
  2315. X    for (s = temp; *s; ++s) {
  2316. X        if (islower(*s))
  2317. X            *s = toupper(*s);
  2318. X    }
  2319. X
  2320. X    strcpy(ans, temp);
  2321. X    return(ans);
  2322. X}
  2323. X
  2324. X/*
  2325. X * Get the path component of the filename.  Translates to upper case.
  2326. X * Returns pointer to a static area.  Doesn't alter leading separator,
  2327. X * always strips trailing separator (unless it is the path itself).
  2328. X */
  2329. X
  2330. Xchar *
  2331. Xget_path(filename)
  2332. Xchar *filename;
  2333. X{
  2334. X    char *s, *end, *begin, *strcpy(), *strrchr(), buf[MAX_PATH];
  2335. X    char drive, *strcat();
  2336. X    static char ans[MAX_PATH];
  2337. X    int has_sep;
  2338. X
  2339. X    strcpy(buf, filename);
  2340. X    begin = buf;
  2341. X                    /* skip drive letter */
  2342. X    drive = '\0';
  2343. X    if (buf[0] && buf[1] == ':') {
  2344. X        drive = (islower(buf[0])) ? toupper(buf[0]) : buf[0];
  2345. X        begin = &buf[2];
  2346. X    }
  2347. X                    /* if absolute path */
  2348. X    if (*begin == '/' || *begin == '\\')
  2349. X        ans[0] = '\0';
  2350. X    else {
  2351. X        if (!drive || drive == *mcwd)
  2352. X            strcpy(ans, mcwd + 2);
  2353. X        else
  2354. X            strcpy(ans, "/");
  2355. X    }
  2356. X                    /* find last separator */
  2357. X    has_sep = 0;
  2358. X    end = begin;
  2359. X    if (s = strrchr(end, '/')) {
  2360. X        has_sep++;
  2361. X        end = s;
  2362. X    }
  2363. X    if (s = strrchr(end, '\\')) {
  2364. X        has_sep++;
  2365. X        end = s;
  2366. X    }
  2367. X                    /* zap the trailing separator */
  2368. X    *end = '\0';
  2369. X                    /* translate to upper case */
  2370. X    for (s = begin; *s; ++s) {
  2371. X        if (islower(*s))
  2372. X            *s = toupper(*s);
  2373. X        if (*s == '\\')
  2374. X            *s = '/';
  2375. X    }
  2376. X                    /* if separator alone, put it back */
  2377. X    if (!strlen(begin) && has_sep)
  2378. X        strcat(ans, "/");
  2379. X
  2380. X    strcat(ans, begin);
  2381. X    return(ans);
  2382. X}
  2383. X
  2384. X/*
  2385. X * get the drive letter designation
  2386. X */
  2387. X
  2388. Xchar
  2389. Xget_drive(filename)
  2390. Xchar *filename;
  2391. X{
  2392. X    if (*filename && *(filename + 1) == ':') {
  2393. X        if (islower(*filename))
  2394. X            return(toupper(*filename));
  2395. X        else
  2396. X            return(*filename);
  2397. X    }
  2398. X    else
  2399. X        return(*mcwd);
  2400. X}
  2401. END_OF_FILE
  2402. if test 2194 -ne `wc -c <'mtools/parse.c'`; then
  2403.     echo shar: \"'mtools/parse.c'\" unpacked with wrong size!
  2404. fi
  2405. # end of 'mtools/parse.c'
  2406. fi
  2407. if test -f 'mtools/patchlevel.h' -a "${1}" != "-c" ; then 
  2408.   echo shar: Will not clobber existing file \"'mtools/patchlevel.h'\"
  2409. else
  2410. echo shar: Extracting \"'mtools/patchlevel.h'\" \(385 characters\)
  2411. sed "s/^X//" >'mtools/patchlevel.h' <<'END_OF_FILE'
  2412. X#define VERSION    "2.0.5"
  2413. X#define DATE    "25 Aug 91"
  2414. X
  2415. X/*
  2416. X * Version 1.0        13 Oct 86
  2417. X * Version 1.1        11 Jan 87
  2418. X * Version 1.2        11 Jun 87
  2419. X * Version 1.3        15 Jun 88
  2420. X * Version 1.4        28 Sep 88
  2421. X * Version 1.5         9 Oct 88
  2422. X * Version 1.6         3 May 89
  2423. X * Version 2.0         8 Sep 90
  2424. X *  patch #1        12 Oct 90
  2425. X *  patch #2        21 Nov 90
  2426. X *  patch #3        28 Nov 90
  2427. X *  patch #4        11 Apr 91
  2428. X *  patch #5        25 Aug 91
  2429. X */
  2430. END_OF_FILE
  2431. if test 385 -ne `wc -c <'mtools/patchlevel.h'`; then
  2432.     echo shar: \"'mtools/patchlevel.h'\" unpacked with wrong size!
  2433. fi
  2434. # end of 'mtools/patchlevel.h'
  2435. fi
  2436. if test -f 'mtools/subdir.c' -a "${1}" != "-c" ; then 
  2437.   echo shar: Will not clobber existing file \"'mtools/subdir.c'\"
  2438. else
  2439. echo shar: Extracting \"'mtools/subdir.c'\" \(2167 characters\)
  2440. sed "s/^X//" >'mtools/subdir.c' <<'END_OF_FILE'
  2441. X#include <stdio.h>
  2442. X#include "msdos.h"
  2443. X
  2444. Xextern int dir_entries;
  2445. Xstatic int descend();
  2446. X
  2447. X/*
  2448. X * Descends the directory tree.  Returns 1 on error.  Attempts to optimize by
  2449. X * remembering the last path it parsed
  2450. X */
  2451. X
  2452. Xint
  2453. Xsubdir(drive, pathname)
  2454. Xchar drive;
  2455. Xchar *pathname;
  2456. X{
  2457. X    char *s, *tmp, tbuf[MAX_PATH], *path, *strcpy();
  2458. X    static char last_drive, lastpath[MAX_PATH];
  2459. X    int code;
  2460. X    void reset_chain();
  2461. X
  2462. X    strcpy(tbuf, pathname);
  2463. X                    /* if paths are same, do nothing */
  2464. X    if (!strcmp(tbuf, lastpath) && last_drive == drive)
  2465. X        return(0);
  2466. X                    /* start at root */
  2467. X    reset_chain(OLD);
  2468. X    strcpy(lastpath, tbuf);
  2469. X    last_drive = drive;
  2470. X                    /* separate the parts */
  2471. X    tmp = &tbuf[1];
  2472. X    for (s = tmp; *s; ++s) {
  2473. X        if (*s == '/') {
  2474. X            path = tmp;
  2475. X            *s = '\0';
  2476. X            if (descend(path))
  2477. X                return(1);
  2478. X            tmp = s + 1;
  2479. X        }
  2480. X    }
  2481. X    code = descend(tmp);
  2482. X    return(code);
  2483. X}
  2484. X
  2485. X/*
  2486. X * Find the directory and load a new dir_chain[].  A null directory
  2487. X * is ok.  Returns a 1 on error.
  2488. X */
  2489. X
  2490. Xstatic int
  2491. Xdescend(path)
  2492. Xchar *path;
  2493. X{
  2494. X    int entry;
  2495. X    unsigned int start;
  2496. X    char *newname, *unix_name();
  2497. X    struct directory *dir, *dir_read();
  2498. X    void reset_chain();
  2499. X                    /* nothing required */
  2500. X    if (*path == '\0')
  2501. X        return(0);
  2502. X
  2503. X    for (entry = 0; entry < dir_entries; entry++) {
  2504. X        dir = dir_read(entry);
  2505. X                    /* if empty */
  2506. X        if (dir->name[0] == 0x0)
  2507. X            break;
  2508. X                    /* if erased */
  2509. X        if (dir->name[0] == 0xe5)
  2510. X            continue;
  2511. X                    /* skip if not a directory */
  2512. X        if (!(dir->attr & 0x10))
  2513. X            continue;
  2514. X
  2515. X        newname = unix_name(dir->name, dir->ext);
  2516. X
  2517. X        /*
  2518. X         * Be careful not to match '.' and '..' with wildcards
  2519. X         */
  2520. X        if (*newname == '.' && *path != '.')
  2521. X            continue;
  2522. X
  2523. X        if (match(newname, path)) {
  2524. X            start = dir->start[1] * 0x100 + dir->start[0];
  2525. X
  2526. X                    /* if '..' points to root */
  2527. X            if (!start && !strcmp(path, "..")) {
  2528. X                reset_chain(OLD);
  2529. X                return(0);
  2530. X            }
  2531. X                    /* fill in the directory chain */
  2532. X            if (fill_chain(start))
  2533. X                return(1);
  2534. X
  2535. X            return(0);
  2536. X        }
  2537. X    }
  2538. X
  2539. X    /*
  2540. X     * If path is '.' or '..', but they weren't found, then you must be
  2541. X     * at root.
  2542. X     */
  2543. X    if (!strcmp(path, ".") || !strcmp(path, "..")) {
  2544. X        reset_chain(OLD);
  2545. X        return(0);
  2546. X    }
  2547. X    fprintf(stderr, "Path component \"%s\" is not a directory\n", path);
  2548. X    return(1);
  2549. X}
  2550. END_OF_FILE
  2551. if test 2167 -ne `wc -c <'mtools/subdir.c'`; then
  2552.     echo shar: \"'mtools/subdir.c'\" unpacked with wrong size!
  2553. fi
  2554. # end of 'mtools/subdir.c'
  2555. fi
  2556. echo shar: End of archive 1 \(of 3\).
  2557. cp /dev/null ark1isdone
  2558. MISSING=""
  2559. for I in 1 2 3 ; do
  2560.     if test ! -f ark${I}isdone ; then
  2561.     MISSING="${MISSING} ${I}"
  2562.     fi
  2563. done
  2564. if test "${MISSING}" = "" ; then
  2565.     echo You have unpacked all 3 archives.
  2566.     rm -f ark[1-9]isdone
  2567. else
  2568.     echo You still need to unpack the following archives:
  2569.     echo "        " ${MISSING}
  2570. fi
  2571. ##  End of shell archive.
  2572. exit 0
  2573.